Edit in JSFiddle

<section class="card-item">
  <figure class="card-image -loading"></figure>
  <div class="card-detail">
    <h3 class="title -loading"></h3>
    <p class="description -loading"></p>
  </div>
</section>
body {
  background-color: white;
  color: #666666;
  padding: 10px;
}

.card-item {
  width: 320px;
  box-shadow: 0 4px 8px rgba(0,0,0,.2);
  transition: .3s;
  
  &:hover {
    box-shadow: 0 8px 16px rgba(0,0,0,.2);
  }
  
  > .card-image {
    margin: 0;
    width: 100%;
    height: 180px;
    
    > .image {
      width: 100%;
      height: 100%;
    }
  }
}

.card-detail {
  padding: 2px 16px;

  > .title {
    letter-spacing: 3px;
  }
  > .description {
    letter-spacing: 1px;
  }
}


.-loading {
  position: relative;
  background-color: #E2E2E2;
  border-radius: 15px;
  
  &.card-image {
    border-radius: 0;
  }
  
  &::after {
    display: block;
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .2), transparent);
    animation: loading 1.5s infinite;
  }
}
@keyframes loading {
  100% {
    transform: translateX(100%);
  }
}
.title.-loading {
  height: 2rem;
}
.description.-loading {
  height: 80px;
}
// LOAD TYPE - No wrap in <body>
window.onload = () => {
  const cardImage = document.getElementsByClassName('card-image')[0];
  const title = document.getElementsByClassName('title')[0];
  const description = document.getElementsByClassName('description')[0];
  
  const render = () => {
    title.innerText = 'ポルトの街並み'
    description.innerText = 'ポルトはポルトガル北部の港湾都市。人口約263,000人。リスボンに次ぐポルトガル第二の都市。同国屈指の世界都市であり、ポルト都市圏では、人口は約160万人を数える。';
    title.classList.remove('-loading');
    description.classList.remove('-loading');
    cardImage.classList.remove('-loading');
  };
  
  const img = new Image(); 
  img.onload = () => {
    render();
    img.classList.add('image');
    cardImage.appendChild(img);
  };
  
  img.onerror = () => {
    render();
  };
  
  // 重い画像ファイル
  setTimeout(() => {
    img.src = 'https://www.pakutaso.com/shared/img/thumb/hiroto_htmachi.jpg';
  }, 5000);
};