PR

【position: absoluteなし】一見重なっている要素をlinear-gradientで解決する

HTML/CSSを学ぶ

こんにちは。今回は、デザイン上の見た目は要素が重なっているように見える要素をスマートに実装する方法を解説したいと思います。

重なっているデザインといえばposition: absolute;を使った実装法がまず思いつくと思いますが、position: absolute;は扱いが難しいプロパティです。気を抜くと要素がはみ出したり、意図しない場所へ行ってしまうなど簡単にレイアウト崩れの原因になります。

なるべくposition: absoluteを使わずに実装できる方法を思いつけるように、いろいろな方法を覚えておきましょう。

前提編

どんなデザイン?

今回例にとるのは、コンテンツ部分に重なるようにボックスが配置されているような場合です。言葉で説明するのは難しいので、下の画像を見てください。

右のボックスが左の画像部分まではみ出していますね。さらに分かりやすいように要素に枠線をつけたのが次の画像です。

SP版は以下の形。こちらも同様に下のボックスが画像部分まで張り出しています。

このような場合に、うまく実装する方法を紹介します。

結論&作るものの確認

実装するものの最終イメージは次の動画で確認してください。

前提としてdestyle.cssというリセットCSSを使っています。

コードは次の通り。画像とコンテンツ部分を単純にdisplay: flex; で並べ、背景をlinear-gradientで部分的に色付けすることでデザイン通りの表現をしています。

index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="./resources/styles/destyle.css" />
    <link rel="stylesheet" href="./resources/styles/style.css" />
    <title>Document</title>
  </head>
  <body>
    <section class="Works">
      <img
        width="350"
        height="238"
        loading="lazy"
        decoding="async"
        src="./resources/images/smoothiesta.webp"
        alt=""
        class="Works-Image"
      />
      <div class="Works__Content">
        <h2 class="Works-Headline">
          <span class="Works-Headline-Main">WORKS</span>
          <span class="Works-Headline-Sub">制作実績</span>
        </h2>
        <p class="Works-Text">
          様々なジャンルのWebサイト制作が可能です。<br />
          ご購入やお申込み数の増加などを実現します!
        </p>
        <a href="#" class="MoreButton">MORE</a>
      </div>
    </section>

    <script>
      const swiper = new Swiper(".swiper", {
        loop: true,
        slidesPerView: 1,
        pagination: {
          el: ".swiper-pagination",
          clickable: true,
        },
      })
    </script>
  </body>
</html>
style.css
img {
  display: block;
  width: 100%;
  height: auto;
}

.Works {
  margin: auto;
  width: 100%;
  max-width: 1260px;
  padding-top: 60px;
  padding-bottom: 60px;
  padding-left: 20px;
  padding-right: 20px;
  display: flex;
  gap: 20px;
  align-items: center;
  background: linear-gradient(to right, #fff 0% 33%, #f0f0f0 33% 100%);
}

@media screen and (max-width: 768px) {
  .Works {
    padding-top: 0;
    padding-bottom: 0;
    flex-direction: column;
    gap: 40px;
    background: linear-gradient(
      to bottom,
      #fff calc(231 / 2 / 375 * 100vw),
      #f0f0f0 calc(231 / 2 / 375 * 100vw)
    );
  }
}

.Works-Image {
  width: 60%;
}

@media screen and (max-width: 768px) {
  .Works-Image {
    width: 100%;
  }
}

.Works__Content {
  width: 35%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30px;
}

@media screen and (max-width: 768px) {
  .Works__Content {
    width: 100%;
    padding-bottom: 60px;
  }
}

.Works-Headline {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.Works-Headline-Main {
  font-size: 36px;
  font-weight: bold;
  color: #391e88;
  font-weight: bold;
}

@media screen and (max-width: 768px) {
  .Works-Headline-Main {
    font-size: 30px;
  }
}

.Works-Headline-Sub {
  font-size: 14px;
  color: #391e88;
  font-weight: bold;
}

.Works-Text {
  line-height: 1.5;
  text-align: center;
}

@media screen and (max-width: 768px) {
  .Works-Text {
    font-size: 14px;
  }
}

.MoreButton {
  border-radius: 9999px;
  width: 200px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(to right, #7633a4, #250d65);
  color: #fff;
}

実装解説の前に | linear-gradientで部分的に背景色をつける方法を知る

背景にグラデーションをつけたい時によく使われるlinear-gradientですが、実は任意の領域を単色で塗ることも可能なんです(下図参照)。

コードは次の通り。

.Box {
  background: linear-gradient(
    to right,
    red 0% 20%,
    orange 20% 40%,
    yellow 40% 60%,
    green 60% 80%,
    blue 80% 100%
  );
}

このように、linear-gradentの色指定部分で、「色 開始点 終了点」と書くことでそのエリアを単色で塗りつぶすことができます。上記のコードはつまり「0~20%部分は赤、20~40%部分はオレンジ、40~60%部分は黄色、・・・」という意味になります。

これを使うことで背景色を部分的につけることが可能です。今回紹介する実装法はこれを利用しています。

参考:https://developer.mozilla.org/ja/docs/Web/CSS/gradient/linear-gradient

実装解説編

大事なのは、要素の組み方をよく考えることです。この記事の最初、画像部分とコンテンツ部分が重なっているという言い方をしましたが、「要素が重なっているのではなく、シンプルに要素を横に並べた上で親要素に部分的に背景色がついている」と考えてみましょう(下画像)。

こうすることで構造が一気に簡単になります。これなら皆さんもすぐに実装イメージがつきますよね。

それでは、まずは一旦背景のことは考えず画像とコンテンツを並べることだけを考えましょう。

<section class="Works">
  <!-- 画像部分 -->
  <img
    width="350"
    height="238"
    loading="lazy"
    decoding="async"
    src="./resources/images/smoothiesta.webp"
    alt=""
    class="Works-Image"
  />

  <!-- コンテンツ部分 -->
  <div class="Works__Content">
    <h2 class="Works-Headline">
      <span class="Works-Headline-Main">WORKS</span>
      <span class="Works-Headline-Sub">制作実績</span>
    </h2>
    <p class="Works-Text">
      様々なジャンルのWebサイト制作が可能です。<br />
      ご購入やお申込み数の増加などを実現します!
    </p>
    <a href="#" class="MoreButton">MORE</a>
  </div>
</section>
img {
  display: block;
  width: 100%;
  height: auto;
}

.Works {
  margin: auto;
  width: 100%;
  max-width: 1260px;
  padding-top: 60px;
  padding-bottom: 60px;
  padding-left: 20px;
  padding-right: 20px;
  display: flex;
  gap: 20px;
  align-items: center;
  background: linear-gradient(to right, #fff 0% 33%, #f0f0f0 33% 100%);
}

.Works-Image {
  width: 60%;
}

.Works__Content {
  width: 35%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 30px;
}


/* ここより下は本題とはあまり関係ないので適当でも良いです。 */
.Works-Headline {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
}

.Works-Headline-Main {
  font-size: 36px;
  font-weight: bold;
  color: #391e88;
  font-weight: bold;
}

.Works-Headline-Sub {
  font-size: 14px;
  color: #391e88;
  font-weight: bold;
}

.Works-Text {
  line-height: 1.5;
  text-align: center;
}

.MoreButton {
  border-radius: 9999px;
  width: 200px;
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(to right, #7633a4, #250d65);
  color: #fff;
}

この時点では、単純に画像とコンテンツ部分が並んだ状態になります(下画像)。

次に、これらの親要素(.Works)に背景色を部分的につけてみましょう。上記で説明したlinear-gradientを使います。

.Works {
  /* 省略 */
  background: linear-gradient(to right, #fff 0% 33%, #f0f0f0 33% 100%); /* 追加 */
}

このlinear-gradientの意味は、「右向きに、0から33%部分は白、33%から100%部分はグレー」という意味になります。.Worksの横幅は最大1260pxなので、それより画面幅が大きい時は両サイドに余白ができます(下画像)。

これでPC版の見た目が完成です。

SP版も発想は全く同じです。一旦背景色以外の部分をSP版にしていきましょう。並び方と各種サイズの調整です。

.Works {
  /* 省略 */
}
@media screen and (max-width: 768px) {
  .Works {
    padding-top: 0;
    padding-bottom: 0;
    flex-direction: column; /* 要素を縦に並べる */
    gap: 40px;
  }
}

.Works-Image {
  /* 省略 */
}
@media screen and (max-width: 768px) {
  .Works-Image {
    width: 100%;
  }
}
.Works__Content {
  /* 省略 */
}
@media screen and (max-width: 768px) {
  .Works__Content {
    width: 100%;
    padding-bottom: 60px;
  }
}
.Works-Headline {
  /* 省略 */
}
.Works-Headline-Main {
  /* 省略 */
}
@media screen and (max-width: 768px) {
  .Works-Headline-Main {
    font-size: 30px;
  }
}
.Works-Headline-Sub {
  /* 省略 */
}
.Works-Text {
  /* 省略 */
}
@media screen and (max-width: 768px) {
  .Works-Text {
    font-size: 14px;
  }
}
.MoreButton {
  /* 省略 */
}

この時点の見た目は、画像とコンテンツが縦に並んでいて背景色はまだPC版と同じです。

では背景色を修正しましょう。縦並びになるので、上から下に領域を数えるためにto right を to bottomにし、あとは同様に設定します。

ただし、縦の場合は数値指定が若干難しくなります。単純に%指定するとその要素の高さに対しての割合になりますが、コンテンツのサイズや改行の位置の関係で画面幅を小さくするとどんどんズレていきます。

30%を指定した場合の挙動が次の動画です。

そこで、高さではなく画面幅に対しての割合をうまく決めたいです。最終的には「画像の半分の位置までは白色」を表現したいので、「画面幅に対する画像の高さの半分はどれくらいか」を書くことができれば良いです。

元々のデザインでは画面幅375pxで作られており、画像の高さは231pxです。よって、「画面幅375pxに対して231 / 2 = 115.5pxになるような割合」を表現すれば良いです。

これをcalcで表現すると、calc(231 / 2 / 375 * 100vw)になります。

.Works {
  /* 省略 */
  background: linear-gradient(
    to bottom, /* 下向きに領域を数える */
    #fff 0% calc(231 / 2 / 375 * 100vw)),
    #f0f0f0 calc(231 / 2 / 375 * 100vw) 100%)
  );
}

「231 / 2 / 375」で「375pxに対する画像の半分の高さがどのくらいの割合か」を表現しています。

それに100vwをかけることで「画面幅に対して変動する」ようになります。

これでSP版の完成です。

この考え方についてより詳しく解説した記事もありますので、合わせてご覧ください。

要素が重なって見えても、考え方次第で構造を単純化できる

というわけで、一見要素が重なって見えるデザインをスマートに実装する方法でした。今回のように、「背景色を部分的につけることができる」という技術的知識とレイアウトの発想次第で実装方針をシンプルにすることができました。

普段の地道な勉強、努力がちゃんと役立ついい例ではないでしょうか。

こういった細かいテクニックをもっと知ってレベルアップしたい方はぜひこちらの本で勉強してみてください!

【脱・初心者】教材だけでは分からない、案件でよく要求される細かいコーディングのテクニック30選 + α - セカヤサBooks
フリーランスのフロントエンドエンジニアとして7年間、サイト制作やWebアプリケーション開発の案件に携わってきた中で「これは伝えたい」と思ったコーディングのテクニックをまとめました! 正直言うと、これができているかどうかが「プロかプロでないか...

コメント

タイトルとURLをコピーしました