CSSアニメーションで映画タイトル風ヒーローエリアを制作

映画のオープニングでよく見られるテキストアニメーションを、HTMLとCSSだけで実装してみました。このアニメーションは、クールな映画のタイトルバックのようなイメージを演出できるので、ウェブサイトのヒーローセクションやランディングページのメインビジュアルとして活用できそうです。

CSS Movie Title Animation

CSSアニメーションを学習中の私にとって、position、animation、@keyframesなど、様々なCSSプロパティを組み合わせてこのようなテキストアニメーションを作ってみるのは良い練習になりました。

シンプルでそこそこインパクトのあるビジュアルを演出できたのではないかな?と思います。
では、コードの主要な部分を解説します。

HTML

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<!-- HTML -->
<body>
<div class="container">
<div class="hero">
<div id="fly-in">
<div>Weave<span>The Web of Innovation</span></div>
<div>Design<span> Shapes the Digital World</span></div>
<div>Web Weaver<span> Connects Ideas</span></div>
<div><span>Very</span>Cinematic</div>
<div>Fade Away<span>into the distance</span></div>
<div><span>Hero</span>Animation</div>
<div><span>Just CSS</span> and HTML</div>
</div>
</div>
<main class="main">
</main>
<footer class="footer">
</footer>
</div>
</body>
<!-- HTML --> <body> <div class="container"> <div class="hero"> <div id="fly-in"> <div>Weave<span>The Web of Innovation</span></div> <div>Design<span> Shapes the Digital World</span></div> <div>Web Weaver<span> Connects Ideas</span></div> <div><span>Very</span>Cinematic</div> <div>Fade Away<span>into the distance</span></div> <div><span>Hero</span>Animation</div> <div><span>Just CSS</span> and HTML</div> </div> </div> <main class="main"> </main> <footer class="footer"> </footer> </div> </body>
<!-- HTML -->
<body>

    <div class="container">
        <div class="hero">

            <div id="fly-in">
                
                <div>Weave<span>The Web of Innovation</span></div>
                <div>Design<span> Shapes the Digital World</span></div>
                <div>Web Weaver<span> Connects Ideas</span></div>
                <div><span>Very</span>Cinematic</div>
                <div>Fade Away<span>into the distance</span></div>
                <div><span>Hero</span>Animation</div>
                <div><span>Just CSS</span> and HTML</div>
            </div>


        </div>



        <main class="main">

        </main>
        <footer class="footer">

        </footer>

    </div>

</body>
  • <div class="container"> は、ページのメインコンテンツを格納するグリッドコンテナです。
  • <div class="hero"> は、ヒーローエリアを定義し、ここにテキストアニメーションが表示されます。
  • <div id="fly-in"> には、アニメーションを適用するテキストが含まれています。各テキストは <div> 要素にラップされ、必要に応じて <span> 要素でスタイリングが適用させています。

CSS

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
/* CSS */
@charset "utf-8";
* {
margin: 0;
padding: 0;
}
body { /* body要素に対して */
/* 背景色を#111に指定 */
background-color: #111;
width: 100vh;
}
.container { display: grid;
grid-template-columns: 1fr;
grid-template-rows: 4fr repeat(2, 0.5fr);
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"hero"
"main"
"footer";
}
.hero { grid-area: hero; }
.main { grid-area: main; }
.footer { grid-area: footer; }
.hero {
/* 背景画像を放射状のグラデーションに指定 */
background-image: radial-gradient(#333, #111);
/* 背景画像を要素のサイズに合わせて伸縮させる */
background-size: cover;
/* 背景画像を繰り返さない */
background-repeat: no-repeat;
/* 背景画像を固定表示する */
background-attachment: fixed;
color: #fff;
text-align: center;
/* 幅を100vwに指定 */
width: 100vw;
font-weight: 700;
/* はみ出した部分を隠す */
overflow: hidden;
font-family: 'Montserrat', sans-serif;
}
#fly-in { /* fly-inというIDに対して */
font-size: 4em;
/* 上下の余白を40vhに指定 */
margin: 40vh auto;
/* 高さを20vhに指定 */
height: 20vh;
/* テキストを大文字に変換する */
text-transform: uppercase;
}
/* fly-inというIDの中のspan要素に対して */
#fly-in span {
/* 表示方法をブロックに指定 */
display: block;
font-size: .4em;
/* 透明度を.8に指定 */
opacity: .8;
}
/* fly-inというIDの中のdiv要素に対して */
#fly-in div {
/* 表示位置を固定に指定 */
position: fixed;
/* 上下の余白を2vhに指定 */
margin: 2vh 0;
/* 透明度を0に指定 */
opacity: 0;
/* 左から10vwの位置に配置 */
left: 10vw;
width: 80vw;
/* switchというアニメーションを32秒かけて線形で無限に繰り返す */
animation: switch 32s linear infinite;
}
/* fly-inというIDの中のdiv要素のn番目に対して、アニメーションの遅延をn秒に指定 */
#fly-in div:nth-child(2) { animation-delay: 4s}
#fly-in div:nth-child(3) { animation-delay: 8s}
#fly-in div:nth-child(4) { animation-delay: 12s}
#fly-in div:nth-child(5) { animation-delay: 16s}
#fly-in div:nth-child(6) { animation-delay: 20s}
#fly-in div:nth-child(7) { animation-delay: 24s}
#fly-in div:nth-child(8) { animation-delay: 28s}
/* switchというアニメーションを定義 */
@keyframes switch {
/* 0%のとき、透明度を0に、ぼかしを20pxに、拡大率を12に指定 */
0% { opacity: 0;filter: blur(20px); transform:scale(12)}
/* 3%のとき、透明度を1に、ぼかしを0に、拡大率を1に指定 */
3% { opacity: 1;filter: blur(0); transform:scale(1)}
/* 10%のとき、透明度を1に、ぼかしを0に、拡大率を.9に指定 */
10% { opacity: 1;filter: blur(0); transform:scale(.9)}
13% { opacity: 0;filter: blur(10px); transform:scale(.1)}
80% { opacity: 0}
100% { opacity: 0}
}
/* CSS */ @charset "utf-8"; * { margin: 0; padding: 0; } body { /* body要素に対して */ /* 背景色を#111に指定 */ background-color: #111; width: 100vh; } .container { display: grid; grid-template-columns: 1fr; grid-template-rows: 4fr repeat(2, 0.5fr); gap: 0px 0px; grid-auto-flow: row; grid-template-areas: "hero" "main" "footer"; } .hero { grid-area: hero; } .main { grid-area: main; } .footer { grid-area: footer; } .hero { /* 背景画像を放射状のグラデーションに指定 */ background-image: radial-gradient(#333, #111); /* 背景画像を要素のサイズに合わせて伸縮させる */ background-size: cover; /* 背景画像を繰り返さない */ background-repeat: no-repeat; /* 背景画像を固定表示する */ background-attachment: fixed; color: #fff; text-align: center; /* 幅を100vwに指定 */ width: 100vw; font-weight: 700; /* はみ出した部分を隠す */ overflow: hidden; font-family: 'Montserrat', sans-serif; } #fly-in { /* fly-inというIDに対して */ font-size: 4em; /* 上下の余白を40vhに指定 */ margin: 40vh auto; /* 高さを20vhに指定 */ height: 20vh; /* テキストを大文字に変換する */ text-transform: uppercase; } /* fly-inというIDの中のspan要素に対して */ #fly-in span { /* 表示方法をブロックに指定 */ display: block; font-size: .4em; /* 透明度を.8に指定 */ opacity: .8; } /* fly-inというIDの中のdiv要素に対して */ #fly-in div { /* 表示位置を固定に指定 */ position: fixed; /* 上下の余白を2vhに指定 */ margin: 2vh 0; /* 透明度を0に指定 */ opacity: 0; /* 左から10vwの位置に配置 */ left: 10vw; width: 80vw; /* switchというアニメーションを32秒かけて線形で無限に繰り返す */ animation: switch 32s linear infinite; } /* fly-inというIDの中のdiv要素のn番目に対して、アニメーションの遅延をn秒に指定 */ #fly-in div:nth-child(2) { animation-delay: 4s} #fly-in div:nth-child(3) { animation-delay: 8s} #fly-in div:nth-child(4) { animation-delay: 12s} #fly-in div:nth-child(5) { animation-delay: 16s} #fly-in div:nth-child(6) { animation-delay: 20s} #fly-in div:nth-child(7) { animation-delay: 24s} #fly-in div:nth-child(8) { animation-delay: 28s} /* switchというアニメーションを定義 */ @keyframes switch { /* 0%のとき、透明度を0に、ぼかしを20pxに、拡大率を12に指定 */ 0% { opacity: 0;filter: blur(20px); transform:scale(12)} /* 3%のとき、透明度を1に、ぼかしを0に、拡大率を1に指定 */ 3% { opacity: 1;filter: blur(0); transform:scale(1)} /* 10%のとき、透明度を1に、ぼかしを0に、拡大率を.9に指定 */ 10% { opacity: 1;filter: blur(0); transform:scale(.9)} 13% { opacity: 0;filter: blur(10px); transform:scale(.1)} 80% { opacity: 0} 100% { opacity: 0} }
/* CSS */

@charset "utf-8"; 

* {
  margin: 0;
  padding: 0;
}

body { /* body要素に対して */
  /* 背景色を#111に指定 */
  background-color: #111; 
  width: 100vh;
}

.container {  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 4fr repeat(2, 0.5fr);
  gap: 0px 0px;
  grid-auto-flow: row;
  grid-template-areas:
    "hero"
    "main"
    "footer";
}

.hero { grid-area: hero; }

.main { grid-area: main; }

.footer { grid-area: footer; }


.hero {  
   /* 背景画像を放射状のグラデーションに指定 */
  background-image: radial-gradient(#333, #111);
   /* 背景画像を要素のサイズに合わせて伸縮させる */
  background-size: cover;
   /* 背景画像を繰り返さない */
  background-repeat: no-repeat;
   /* 背景画像を固定表示する */
  background-attachment: fixed;
  color: #fff;
  text-align: center;
   /* 幅を100vwに指定 */
  width: 100vw;
  font-weight: 700;
   /* はみ出した部分を隠す */  
  overflow: hidden;
  font-family: 'Montserrat', sans-serif;

}

#fly-in { /* fly-inというIDに対して */
  font-size: 4em;
   /* 上下の余白を40vhに指定 */  
  margin: 40vh auto;
   /* 高さを20vhに指定 */
  height: 20vh;
   /* テキストを大文字に変換する */  
  text-transform: uppercase;

}

   /* fly-inというIDの中のspan要素に対して */
#fly-in span {
   /* 表示方法をブロックに指定 */  
  display: block;
  font-size: .4em;
   /* 透明度を.8に指定 */
  opacity: .8;

}
   /* fly-inというIDの中のdiv要素に対して */
#fly-in div {
   /* 表示位置を固定に指定 */  
  position: fixed;
   /* 上下の余白を2vhに指定 */  
  margin: 2vh 0;
   /* 透明度を0に指定 */
  opacity: 0;
   /* 左から10vwの位置に配置 */
  left: 10vw;
  width: 80vw;
   /* switchというアニメーションを32秒かけて線形で無限に繰り返す */
  animation: switch 32s linear infinite;

}
 /* fly-inというIDの中のdiv要素のn番目に対して、アニメーションの遅延をn秒に指定 */
#fly-in div:nth-child(2) { animation-delay: 4s}

#fly-in div:nth-child(3) { animation-delay: 8s} 
#fly-in div:nth-child(4) { animation-delay: 12s} 
#fly-in div:nth-child(5) { animation-delay: 16s} 
#fly-in div:nth-child(6) { animation-delay: 20s} 
#fly-in div:nth-child(7) { animation-delay: 24s} 
#fly-in div:nth-child(8) { animation-delay: 28s} 

/* switchというアニメーションを定義 */
@keyframes switch { 
    /* 0%のとき、透明度を0に、ぼかしを20pxに、拡大率を12に指定 */  
    0% { opacity: 0;filter: blur(20px); transform:scale(12)}
    /* 3%のとき、透明度を1に、ぼかしを0に、拡大率を1に指定 */    
    3% { opacity: 1;filter: blur(0); transform:scale(1)}
    /* 10%のとき、透明度を1に、ぼかしを0に、拡大率を.9に指定 */
    10% { opacity: 1;filter: blur(0); transform:scale(.9)}
    13% { opacity: 0;filter: blur(10px); transform:scale(.1)} 
    80% { opacity: 0}
    100% { opacity: 0}
}
  • .container display: grid;グリッドレイアウトを使用しており.hero, .main, .footerエリアを定義しています1
  • .hero エリアには、放射状のグラデーション背景を設定しテキストは中央揃えで白色になっています。
  • #fly-in で、テキストアニメーションのためのスタイルが適用しています。テキストは大文字に変換し、フォントサイズや透明度を調整しています。
  • @keyframes switch は、テキストがフェードインして拡大縮小するアニメーションを定義しています。このアニメーションは、#fly-in の各子要素に適用し、animation-delay を使用してそれぞれ異なるタイミングでアニメーションが開始されるようにしています。
  • infinite を指定することでアニメーションは無限に繰り返され、テキストは画面上でフェードインし、拡大縮小しながら動きます。これにより、映画のタイトルバックのようなダイナミックな視覚効果が生まれます。

アニメーションの遅延の時間などを調整すると、また違った雰囲気が出るので、作っていて楽しかったコードです2

  1. CodePenではmain以降のコードは省略しています。 ↩︎
  2. こちら を参考に作成しました ↩︎

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です