HTML/CSS

【CSS】メディアレイアウトの実装方法を徹底解説!

Webサイトで必ずと言って良いほど見かける画像とテキストが横並びになっているデザイン、通称「メディアレイアウト」の実装方法を解説します。

記事の後半ではメディアレイアウトを応用したデザインの実装方法も解説します。

メディアレイアウトとは?

メディアレイアウトとは、画像とテキストが横並びになっているデザインです。サイトの種類に関わらず登場頻度が高いデザインだと思います。

情報としては、事業内容やサービスの特徴などの紹介が多いですね。3つほど配置されていて、画像とテキスト欄が左右交互になっているというのが一般的なデザインだと思います。

他にも、ブログの記事のリンクとなっているメディアレイアウトや要素が不規則に重なり合うブロークングリッドレイアウトとなっているメディアレイアウトもあります。

メディアレイアウトは登場頻度が高いデザインとなるため、是非とも実装方法を覚えておきたいですね。次のセクションからメディアレイアウトの実装方法を解説していきます。

基本的なメディアレイアウトの実装方法

まず最初にシンプルなデザインのメディアレイアウトの実装方法を解説していきます。

ブログなどの記事のリンク

ブログの記事のサムネイルとタイトル・抜粋文が横並びになっているデザインです。要素全体がリンクになっているのが特徴ですね。

<div class="container">
      <ul class="media-list">
        <li class="media-list__item">
          <a href="#" class="media-list__link">
            <div class="media-list__thumb">
              <img src="img/001.jpg" alt="" />
            </div>
            <div class="media-list__body">
              <p class="media-list__title">タイトルテキスト</p>
              <p class="media-list__text">
                この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
              </p>
            </div>
          </a>
        </li>
        <li class="media-list__item">
          <a href="#" class="media-list__link">
            <div class="media-list__thumb">
              <img src="img/002.jpg" alt="" />
            </div>
            <div class="media-list__body">
              <p class="media-list__title">タイトルテキスト</p>
              <p class="media-list__text">
                この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために。
              </p>
            </div>
          </a>
        </li>
        <li class="media-list__item">
          <a href="#" class="media-list__link">
            <div class="media-list__thumb">
              <img src="img/003.jpg" alt="" />
            </div>
            <div class="media-list__body">
              <p class="media-list__title">タイトルテキスト</p>
              <p class="media-list__text">
                この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れてい                ます。この文章はダミーです。文字の大きさ、
              </p>
            </div>
          </a>
        </li>
      </ul>
    </div>
img {
  max-width: 100%;
  height: auto;
}

.container {
  max-width: 1000px;
  margin: 50px auto;
  padding: 0 20px;
}

.media-list__link {
  display: flex;
  align-items: center;
  column-gap: 20px;
  padding: 20px 0;
  border-bottom: 1px solid #e7e7e7;
}

.media-list__thumb {
  width: 30%;
  flex-shrink: 0;
}

.media-list__body {
  width: 70%;
}

.media-list__title {
  margin-bottom: 20px;
  font-size: 20px;
  font-weight: bold;
}

.media-list__text {
  line-height: 1.5;
  font-size: 14px;
}

そこまで難しい実装方法ではないので詳細な解説は省きますが、タイトルや抜粋文が長文だった場合を想定して、指定の行数以上になったら3点リーダーを表示させたりするなどの対応が必要になる事があります。

.media-list__title {
  margin-bottom: 20px;
  font-size: 20px;
  font-weight: bold;
  // 抜粋文を2行で区切る
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.media-list__text {
  line-height: 1.5;
  font-size: 14px;
  // 抜粋文を3行で区切る
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

画像エリアとテキストエリアが1:1(左右交互の配置)

こちらのデザインもよく見かけると思います。主に事業内容や特徴などを説明している事が多いです。左右交互に配置されているのが特徴ですね。

<div class="container">
      <section class="media">
        <div class="media__thumb">
          <img class="media__img" src="img/001.jpg" alt="" />
        </div>
        <div class="media__body">
          <h3 class="media__title">常夏の楽園</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
      <section class="media media--reverse">
        <div class="media__thumb">
          <img class="media__img" src="img/002.jpg" alt="" />
        </div>
        <div class="media__body">
          <h3 class="media__title">ハワイの青い空</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
      <section class="media">
        <div class="media__thumb">
          <img class="media__img" src="img/003.jpg" alt="" />
        </div>
        <div class="media__body">
          <h3 class="media__title">天国の海</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
    </div>
.container {
  max-width: 1000px;
  margin: 50px auto;
  padding: 0 20px;
}

.media {
  display: flex;
  flex-direction: row;
}

.media--reverse {
  flex-direction: row-reverse;
}

.media__thumb {
  width: 50%;
}

.media__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  width: 50%;
  padding: 25px;
  background-color: #f9fae9;
}

.media__title {
  margin-bottom: 20px;
  font-size: 20px;
  font-weight: bold;
}

.media__text {
  line-height: 1.5;
  font-size: 14px;
}

こちらのデザインも比較的実装が簡単だと思います。

ページ公開後に変更でテキスト量が増えることを想定して、テキストエリアと画像エリアの高さが常に揃うようにしておくのが良いと思います。

// テキスト量に応じて画像を伸ばし歪まないようにトリミングする
.media__img {
  height: 100%;
  object-fit: cover;
}

応用的なメディアレイアウト実装方法

基本のデザインの実装方法を学んだところで続いては、応用的なデザインのメディアレイアウトの実装方法を解説していきます。

パッと見難しそうに見えるデザインも考え方のコツを掴めば意外と簡単に出来てしまいます。また、このセクションからはレスポンシブでスマホのデザインも含めて解説していきます。

画像エリアに要素を重ねる

要素の後ろに影のように背景色付きの要素を重ねるデザインもよく見かけます。このデザインは擬似要素を使用する事で実現出来ます。

<div class="container">
      <section class="media">
        <div class="media__thumb media__thumb--normal">
          <img class="media__img" src="img/001.jpg" alt="" />
        </div>
        <div class="media__body">
          <h3 class="media__title">常夏の楽園</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
      <section class="media media--reverse">
        <div class="media__thumb media__thumb--reverse">
          <img class="media__img" src="img/002.jpg" alt="" />
        </div>
        <div class="media__body">
          <h3 class="media__title">ハワイの青い空</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
      <section class="media">
        <div class="media__thumb media__thumb--normal">
          <img class="media__img" src="img/003.jpg" alt="" />
        </div>
        <div class="media__body">
          <h3 class="media__title">天国の海</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
    </div>
img {
  max-width: 100%;
  height: auto;
}

body {
  overflow-x: hidden;
}

.container {
  padding: 0 20px;
  margin-top: 30px;
}

@media screen and (min-width: 768px) {
  .container {
    max-width: 1000px;
    margin: 50px auto;
  }
}

.media:not(:last-child) {
  margin-bottom: 50px;
}

@media screen and (min-width: 768px) {
  .media {
    display: flex;
    flex-direction: row;
  }

  .media:not(:last-child) {
    margin-bottom: 30px;
  }
}

.media--reverse {
  flex-direction: row-reverse;
}

.media__thumb {
  position: relative;
}

@media screen and (min-width: 768px) {
  .media__thumb {
    width: 50%;
  }
}

.media__thumb::after {
  content: "";
  display: block;
  position: absolute;
  top: -20px;
  width: 100%;
  height: 100%;
  background-color: #cdecf0;
  z-index: -1;
}

@media screen and (min-width: 768px) {
  .media__thumb::after {
    top: -30px;
  }
}

.media__thumb--normal::after {
  right: 25px;
}

@media screen and (min-width: 768px) {
  .media__thumb--normal::after {
    right: 50px;
  }
}

.media__thumb--reverse::after {
  left: 30px;
}

@media screen and (min-width: 768px) {
  .media__thumb--reverse::after {
    left: 50px;
  }
}

@media screen and (min-width: 768px) {
  .media__img {
    height: 100%;
    object-fit: cover;
  }
}

.media__body {
  padding: 25px;
}

@media screen and (min-width: 768px) {
  .media__body {
    display: flex;
    flex-direction: column;
    justify-content: center;
    width: 50%;
  }
}

.media__title {
  margin-bottom: 15px;
  font-size: 18px;
  font-weight: bold;
  text-align: center;
}

@media screen and (min-width: 768px) {
  .media__title {
    margin-bottom: 20px;
    font-size: 20px;
  }
}

.media__text {
  line-height: 1.5;
  font-size: 14px;
}

画像の後ろにいる影の要素は、レスポンシブで画像のサイズが変わる場合に、それに連動してサイズを変化させる必要があります。

そのため画像エリアに擬似要素を設定し、position: absolute絶対配置をしてwidthとheightを100%にする事で画像エリアと同じサイズかつ連動して形が変化する影の要素を作ります。

あとは影の要素をtop/bottom/right/leftプロパティで必要な量だけ移動させたら完成です。閲覧するデバイスによっては画面外に影の要素が移動してしまうので、bodyタグにoverflow-x: hiddenの指定をしましょう。

影の要素をコンテンツ幅に関係なく、ブラウザの端まで伸ばしたい場合は、影の要素のwidthに50vwを指定しましょう。

画像エリアとテキストエリアが重なりあう

通常のメディアレイアウトだと規則的に並んでいるので単調な見た目になりがちです。これをアレンジしたテキストエリアと画像エリアをずらして重なり合うデザインの実装方法を解説します。

<div class="container">
      <section class="media media--normal">
        <div class="media__thumb media__thumb--normal">
          <img class="media__img" src="img/001.jpg" alt="" />
        </div>
        <div class="media__body media__body--normal">
          <h3 class="media__title">常夏の楽園</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
      <section class="media media--reverse">
        <div class="media__thumb media__thumb--reverse">
          <img class="media__img" src="img/002.jpg" alt="" />
        </div>
        <div class="media__body media__body--reverse">
          <h3 class="media__title">ハワイの青い空</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
      <section class="media">
        <div class="media__thumb media__thumb--normal">
          <img class="media__img media__img--normal" src="img/003.jpg" alt="" />
        </div>
        <div class="media__body media__body--normal">
          <h3 class="media__title">天国の海</h3>
          <p class="media__text">
            この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
          </p>
        </div>
      </section>
    </div>
img {
  max-width: 100%;
  height: auto;
}

.container {
  max-width: 1000px;
  margin: 50px auto;
  padding: 0 20px;
}

.media {
  margin-bottom: 30px;
}

@media screen and (min-width: 768px) {
  .media {
    display: flex;
    margin-bottom: 80px;
  }

  .media--normal {
    flex-direction: row;
  }

  .media--reverse {
    flex-direction: row-reverse;
  }
}

.media__thumb {
  position: relative;
  z-index: 1;
}

@media screen and (min-width: 768px) {
  .media__thumb {
    width: 50%;
  }
}

.media__thumb--normal {
  margin-left: -20px;
}

.media__thumb--reverse {
  margin-right: -20px;
}

@media screen and (min-width: 768px) {
  .media__thumb--normal {
    margin-left: 0;
  }

  .media__thumb--reverse {
    margin-right: 0;
  }
}

.media__img {
  height: 100%;
  object-fit: cover;
}

.media__body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 60px 25px 40px;
  background-color: #f9fae9;
}

@media screen and (min-width: 768px) {
  .media__body {
    position: relative;
    top: 40px;
    width: calc(50% + 80px);
    padding: 30px;
  }
}

.media__body--normal {
  margin-top: -40px;
  margin-right: -20px;
}

.media__body--reverse {
  margin-top: -40px;
  margin-left: -20px;
}

@media screen and (min-width: 768px) {
  .media__body--normal {
    margin-top: 0;
    margin-right: 0;
    margin-left: -80px;
    padding-left: 110px;
  }

  .media__body--reverse {
    margin-top: 0;
    margin-right: -80px;
    margin-left: 0;
    padding-left: 110px;
  }
}

.media__title {
  margin-bottom: 20px;
  font-size: 20px;
  font-weight: bold;
  text-align: center;
}

.media__text {
  line-height: 1.5;
  font-size: 14px;
}

ずらしの実装はネガティブマージンを使用して実現させています。ネガティブマージンとはマイナスの値を指定したmarginプロパティのことです。

marginプロパティにマイナスの数値を指定すると、プラスの数値を指定した時と逆の結果となります。具体的には指定した要素が指定方向に関係なく、引き伸ばされるような挙動をとります。

この引き伸ばされる挙動は、コンテンツ幅を無視して子要素の幅を画面いっぱいにする時などに利用されます。

今回のデザインでは、ネガティブマージンで引き伸ばす分の数字をあらかじめwidthに指定して、テキストエリアの幅を大きくし、ネガティブマージンで大きくした幅を相殺しています。

.media__body {
   width: calc(50% + 80px); /* 80px分要素幅を広げる */
}

.media__body--normal {
   margin-left: -80px; /* 80px分広げた幅を相殺する */
}

画像とテキストエリアが重なっているように見えるデザインは、このようにテキストエリアを伸ばす事で実現する事が可能です。

まとめ

一見すると難しそうに見えるデザインも分解して1つ1つの要素をよく観察する事で実装方法を検討出来ます。個人的にはデザインの見た目にとらわれ過ぎずに考える事がポイントかなと思います。

position、擬似要素、ネガティブマージン、この3つを駆使する事が鍵になるので自信がない人は練習してどういった挙動を取るのか把握しておきましょう。

最後まで読んでいただきありがとうございました!

関連記事