iPhone SEのWebデザインがすごい!テクニックを学んでスキルアップしよう!



iPhone SEのWebデザインがすごい!テクニックを学んでスキルアップしよう!

常に業界の最先端を走るApple社。

2020年に発売したiPhone SEの商品ページ、無茶苦茶かっこいいです。(商品ページ

スマホでもインタラクティブな挙動を可能にし、Webデザイナーなら誰しもが「おっ、これどうやって処理しているんだ」と思うページ。

すごいところは高度な JavaScript で処理されているため解説は難しいですが、HTMLの基本的な部分がしっかり応用され、デザインに活かされています。

今回はHTML/CSS初心者でも知っておきたい iPhone SE ページのWebデザインテクニックをご紹介していきますね。

目次
  1. iPhone SEのWebデザインがすごい!テクニックを学んでスキルアップしよう!
  2. 文章を上手に改行するテクニックのwbrタグ
  3. 要素の個別操作を助けてくれるdata属性
  4. 画像制御に欠かせないsrcset属性
  5. グリッドレイアウトを手伝ってくれるFlex
  6. CSSアニメーションっぽいmatrix()
  7. まとめ

iPhone SEのWebデザインがすごい!テクニックを学んでスキルアップしよう!

文章を上手に改行するテクニックのwbrタグ

image

現在のWebページのデザイン環境は非常に複雑で、iPhoneの場合はグローバス市場をターゲットにしているため、多言語に多デバイスと何かと制御が難しい環境。

そんな中でも iPhone SE のページは文章を上手に区切り、どのデバイスで見ても「あれっ、変なの」と感じさせない制御をとっています。 その秘密はHTMLタグの <wbr>

<wbr> ・・・ 画面幅によって単語を切り分ける機会を与える

実際に日本語の iPhone SE のHTMLコードを見てみますと、頻繁に <wbr> が使われています。

image

一見すると便利そうに見える <wbr> ですが、実は日本語の場合うまく”ブレイク”してくれません。

image

サンプルページ

上図のコードを今見る

        <!DOCTYPE html>
        <html lang="ja">
        <head>
            <meta charset="UTF-8" />
            <title>wbr demo</title>
            <meta name="viewport" content="width=device-width, user-scalable=no">
            <style>
              body{
                max-width:600px;
                margin:0 auto;
                padding: 1rem;
                text-align:center;
                background-color: #ccffff;
              }
            </style>
        </head>
        <body>
          <main>
            <article>
              <h2>日本語 wbr</h2>
              <h3>自分の住む街は、自分たちできれいにしよう、大変だけどね。</h3>
              <h3>自分の住む街は、自分たちで<wbr>きれいにしよう、大変だけどね。</h3>
              <hr>
              <h2>英語 wbr(空白あり)</h2>
              <h3>Let's clean our own city by ourselves.</h3>
                <h3>Let's clean our own city <wbr>by ourselves.</h3>
              <hr>
              <h2>英語 wbr(空白なし)</h2>
              <h3>Let'sCleanOurOwnCityByOurselves.</h3>
              <h3>Let'sCleanOurOwnCity<wbr>ByOur<wbr>selves.</h3>
              <hr>
              <h2>日本語 幅0のスペース</h2>
              <div style="word-break:keep-all;">
                <h3>自分の住む街は、&#8203;自分たちできれいにしよう、&#8203;大変だけどね。</h3>
              </div>
              <hr>
              <p><a href="https://pythonchannel.com">by 町のWeb屋 大島</a></p>
            </article>
          </main>
        </body>
        </html>
    

私もはじめて <wbr> を使ったのですが、日本語は❌で、英語の場合もスペースがない場合のみ <wbr> が働きます(上図参照)。iPhone SEのページは特殊な処理を施している感じですが、簡単にこの <wbr> を再現しようと思いますと、「スペース・ゼロの空白」が便利です。

&#8203; という記号をHTMLコードの文章内に入れると、ブラウザは ”​=空白” とみなして、画面の切れ目で改行してくれます。 「なかなか端末毎で改行がうまくいかないな」という時の一つのテクニックとしてご参考ください。

尚、文章が固定であれば &#8203; で制御できますが、中には動的な文章を制御しないといけない場合も。そんな時は Budou という Python ライブラリを使えば日本語も中国語も <wbr> のような振る舞いができるようになりますね。

要素の個別操作を助けてくれるdata属性

image

通常は class や id によって HTML の要素を個別制御するものの、場合によってはもっと細かく HTML の各要素を制御したい場合も。そんな時は HTML の「data属性」が便利。

iPhone SE の Webページの中でも数カ所 data属性 は登場してきて、端末毎のレイアウト調整などを行っています。

data属性は CSS 的にも JavaScript 的にも使える HTML 属性なので知っておくと便利。例えば同じボタン処理でも、data属性を使うのと使わないのではコード量が違ってきます。

image

data属性なしのページ data属性ありのページ

image

data-tag なしのコードを今見る

        <!DOCTYPE html>
        <html lang="ja">
        <head>
          <meta charset="UTF-8" />
          <title>Flappy Bird</title>
          <meta name="viewport" content="width=device-width, user-scalable=no">
          <style>
            body{
              max-width:600px;
              margin:0 auto;
              padding: 1rem;
              text-align:center;
              background-color: #ccffff;
            }
        
            /* popup image */
            .popup-overlay ,.popup-overlay2 ,.popup-overlay3{
                transform: translate(-50%, -50%);
                -webkit-transform: translate(-50%, -50%);
                visibility: hidden;
                position: absolute;
                background: #ffffff;
                max-width: 500px;
                left: 50%;
              }
            .popup-overlay.active, .popup-overlay2.active , .popup-overlay3.active{
              visibility: visible;
              text-align: center;
            }
            .popup-content , .popup-content2, .popup-content3{
              visibility: hidden;
            }
            .popup-content.active ,.popup-content2.active, .popup-content3.active{
              visibility: visible;
              position: relative;
            }
            .popup-text{
              position: absolute;
              left: 50%;
              top: 50%;
              margin-top: 13rem;
              transform: translate(-50%, -50%);
              background-color: rgba(80, 80, 80, 0.97);
              border-radius: 5px;
              padding: 2rem;
              width: 65vw;
              color: white;
              border: #7fff00 solid 2px;
            }
            a{
              color: white;
            }
            #popup-image-button {
              background-color: gray;
              color: white;
              margin: 1rem 0;
              font-size: 1.2rem;
              padding: 0.5rem 1.5rem;
              border-radius: 1rem;
            }
            .active #popup-image-button:hover {
              font-size: 1.2rem;
              background-color: white;
              color: gray;
            }
            .popup-content .popup-text p{
              text-align: left;
            }
            #popup-image-button {
              margin: 1rem 0;
              font-size: 1.2rem;
              color: #fff;
              background-color: #daa520;
              padding: 0.5rem 1.5rem;
              border-radius: 1rem;
            }
            #popup-image-button:hover {
              background-color: #fff;
              color: #daa520;
              font-size: 1.2rem;
            }
          </style>
        
          <body>
            <div class="popup-overlay">
              <div class="popup-content">
                <div class="popup-text">
                  <h2>Webサイトの制作・修正</h2>
                  <p>目的に応じた Web サイトの制作を承ります。</p>
                  <p>また既存サイトの修正やスマホ対応なども可能です。</p>
                  <p>実績は自社サイトや京都の葬儀社 「<a href="https://maruichi-kyoto.com">まるいち</a>さん」 と少ないですが、5年以上続けているテクニカルWebライターによる、Web 全般の広い知識を持っています。また2018年には私の個人ブログサイトを 100万円で売却した経験も。</p>
                  <button class="close" id="popup-image-button" style="margin:16px">閉じる</button>
                </div>
              </div>
            </div>
            <button class="open" id="popup-image-button">詳しく見る</button>
        
            <div class="popup-overlay2">
              <div class="popup-content2">
                <div class="popup-text">
                  <h2>AI(人工知能) × Web</h2>
                  <p>本サイトでも採用している自然言語処理の「ボットくん」をはじめ、統計データからなる "予測" 機能を搭載した Webサイトの制作が可能。</p>
                  <p>AI開発については、使用目的、ラーニング用データ、補正と開発には時間がかかる傾向です。</p>
                    <button class="close2" id="popup-image-button" style="margin:16px">閉じる</button>
                </div>  
              </div>
            </div>
            <button class="open2" id="popup-image-button">詳しく見る</button>
            
            <div class="popup-overlay3">
              <div class="popup-content3">
                <div class="popup-text">
                  <h2>AI(人工知能) × Web</h2>
                  <p>本サイトでも採用している自然言語処理の「ボットくん」をはじめ、統計データからなる "予測" 機能を搭載した Webサイトの制作が可能。</p>
                  <p>AI開発については、使用目的、ラーニング用データ、補正と開発には時間がかかる傾向です。</p>
                    <button class="close3" id="popup-image-button" style="margin:16px">閉じる</button>
                </div>  
              </div>
            </div>
            <button class="open3" id="popup-image-button">詳しく見る</button>
            <hr>
            <p><a href="https://pythonchannel.com">by 町のWeb屋 大島</a></p>
            <script src="https://pythonchannel.com/static/machi_web/jquery.min.js"></script>
        
            <script>
              $(".open").on("click", function() {
                $(".popup-overlay, .popup-content").addClass("active");
              });
              $(".close, .popup-overlay").on("click", function() {
                $(".popup-overlay, .popup-content").removeClass("active");
              });
        
              $(".open2").on("click", function() {
                $(".popup-overlay2, .popup-content2").addClass("active");
              });
              $(".close2, .popup-overlay").on("click", function() {
                $(".popup-overlay2, .popup-content2").removeClass("active");
              });
        
              $(".open3").on("click", function() {
                $(".popup-overlay3, .popup-content3").addClass("active");
              });
              $(".close3, .popup-overlay").on("click", function() {
                $(".popup-overlay3, .popup-content3").removeClass("active");
              });
            </script>
          </body>
        </html>
        
    
data-tag ありのコードを今見る

        <!DOCTYPE html>
        <html lang="ja">
        <head>
          <meta charset="UTF-8" />
          <title>Flappy Bird</title>
          <meta name="viewport" content="width=device-width, user-scalable=no">
          <style>
            body{
              max-width:600px;
              margin:0 auto;
              padding: 1rem;
              text-align:center;
              background-color: #ccffff;
            }
            /* popup image */
            .popup-overlay1 ,.popup-overlay2 ,.popup-overlay3{
                transform: translate(-50%, -50%);
                -webkit-transform: translate(-50%, -50%);
                visibility: hidden;
                position: absolute;
                background: #ffffff;
                max-width: 500px;
                left: 50%;
              }
            .popup-overlay1.active, .popup-overlay2.active , .popup-overlay3.active{
              visibility: visible;
              text-align: center;
            }
            .popup-content1 , .popup-content2, .popup-content3{
              visibility: hidden;
            }
            .popup-content1.active ,.popup-content2.active, .popup-content3.active{
              visibility: visible;
              position: relative;
            }
            .popup-text{
              position: absolute;
              left: 50%;
              top: 50%;
              margin-top: 13rem;
              transform: translate(-50%, -50%);
              background-color: rgba(80, 80, 80, 0.97);
              border-radius: 5px;
              padding: 2rem;
              width: 65vw;
              color: white;
              border: #7fff00 solid 2px;
            }
            a{
              color: white;
            }
            #popup-image-button {
              background-color: gray;
              color: white;
              margin: 1rem 0;
              font-size: 1.2rem;
              padding: 0.5rem 1.5rem;
              border-radius: 1rem;
            }
            .active #popup-image-button:hover {
              font-size: 1.2rem;
              background-color: white;
              color: gray;
            }
            .popup-content .popup-text p{
              text-align: left;
            }
            #popup-image-button {
              margin: 1rem 0;
              font-size: 1.2rem;
              color: #fff;
              background-color: #bd20da;
              padding: 0.5rem 1.5rem;
              border-radius: 1rem;
            }
            #popup-image-button:hover {
              background-color: #fff;
              color: #daa520;
              font-size: 1.2rem;
            }
          </style>
        
          <body>
            <div class="popup-overlay1">
              <div class="popup-content1">
                <div class="popup-text">
                  <h2>Webサイトの制作・修正</h2>
                  <p>目的に応じた Web サイトの制作を承ります。</p>
                  <p>また既存サイトの修正やスマホ対応なども可能です。</p>
                  <p>実績は自社サイトや京都の葬儀社 「<a href="https://maruichi-kyoto.com">まるいち</a>さん」 と少ないですが、5年以上続けているテクニカルWebライターによる、Web 全般の広い知識を持っています。また2018年には私の個人ブログサイトを 100万円で売却した経験も。</p>
                  <button  data-show="true" data-pop-id="1" class="close1" id="popup-image-button" style="margin:16px">閉じる</button>
                </div>
              </div>
            </div>
        
            <div class="popup-overlay2">
              <div class="popup-content2">
                <div class="popup-text">
                  <h2>AI(人工知能) × Web</h2>
                  <p>本サイトでも採用している自然言語処理の「ボットくん」をはじめ、統計データからなる "予測" 機能を搭載した Webサイトの制作が可能。</p>
                  <p>AI開発については、使用目的、ラーニング用データ、補正と開発には時間がかかる傾向です。</p>
                    <button  data-show="true" data-pop-id="2" class="close2" id="popup-image-button" style="margin:16px">閉じる</button>
                </div>  
              </div>
            </div>
            
            <div class="popup-overlay3">
              <div class="popup-content3">
                <div class="popup-text">
                  <h2>ECサイト</h2>
                  <p>ネットショッピングサイトも頑張るよ</p>
                    <button  data-show="true" data-pop-id="3" class="close3" id="popup-image-button" style="margin:16px">閉じる</button>
                </div>  
              </div>
            </div>
            
            <button data-show="true" data-pop-id="1" id="popup-image-button"class="open1">詳しく見る</button>
            <button data-show="true" data-pop-id="2" id="popup-image-button"class="open2">詳しく見る</button>
            <button data-show="true" data-pop-id="3" id="popup-image-button"class="open3">詳しく見る</button>
            
            <hr>
            <p><a href="https://pythonchannel.com">by 町のWeb屋 大島</a></p>
        
            <script src="https://pythonchannel.com/static/machi_web/jquery.min.js"></script>
        
            <script>
              let buttons = document.querySelectorAll("button");
              let buttonsArray = Array.from(buttons);
              buttonsArray.forEach(function(elem){
                //console.log(elem.dataset.popId);
                var popId = elem.dataset.popId;
                var open = ".open" + popId;
                var close = ".close" + popId + ", .popup-overlay";
                var overlayAndContent = ".popup-overlay" + popId + ", .popup-content" + popId ;
        
                $(open).on("click", function() {
                  $(overlayAndContent).addClass("active");
                });
                $(close).on("click", function() {
                  $(overlayAndContent).removeClass("active");
                });
              });
        
            </script>
          </body>
        </html>
    

上図のように出力結果は同じ JavaScript でも、コードは data属性を”使う場合”と”使わない場合”で違います。今回のように3つぐらいの要素の制御であればコード量はそれほど多く違いませんが、data属性なしの場合はボタン量と共にコード量も比例して増えていきます。

一方、data属性を使う場合はボタン量が増えても、JavaScriptの量は一定。ボタン毎に異なる処理を行いたい場合は、data属性を使う方が良さそうですね。

画像制御に欠かせないsrcset属性

image

WordPressなどで使われている画像制御の srcset。

srcset・・・HTML側で画面幅に応じた画像出力が制御できる

iPhone SE のページ内でも多数 srcset が使われており、iPhone の場合はさらに一歩進んだ srcset の使い方で、各画像サイズに Retinaディスプレイ用の画像を用意。

通常は srcset="〇〇.jpg" で終わるところを

srcset="〇〇.jpg, ●●.jpg 2x"

と 2x を別途追記。これでユーザーの端末毎に違う画面解像度に合わせた適切な綺麗な画像を出力することができますね。

尚、 2x と追記すれば解像度の高い画像を自動で生成して、出力してくれるわけではなく、別途 Retina用の高解像度の画像を用意する必要があります。 つまり iPhone SE の Webページでは、1枚の画像表示に対して、 6種類以上の異なるサイズの画像を用意してセット。 この大変な作業、画像サイズを自動でリサイズしてくれるプログラムが必要かもしれませんね。

参考までにシンプルな srcset のサンプルプログラムを作りましたので、 srcset 興味ある方、ご参考ください。

image

サンプルページ

上図のコードを今見る

        <!DOCTYPE html>
        <html lang="ja">
        <head>
          <meta charset="UTF-8" />
          <title>Flappy Bird</title>
          <meta name="viewport" content="width=device-width, user-scalable=no">
          <style>
            body{
              max-width:1200px;
              margin:0 auto;
              padding: 1rem;
              text-align:center;
              background-color: #ccffff;
            }
          </style>
        </head>
        <body>
          <main>
            <article>
              <h2>普通の srcset の処理</h2>
              <picture>
                <source media="(min-width:650px)" srcset="https://pythonchannel.com/static/images/codecamp/img/srcset/M.jpg">
                <source media="(min-width:420px)" srcset="https://pythonchannel.com/static/images/codecamp/img/srcset/S.jpg">
                <img src="https://pythonchannel.com/static/images/codecamp/img/srcset/L.jpg" alt="srcset" style="width:100%;">
              </picture>
              <hr>
              <h2>Retina対応の処理</h2>
              <picture>
                <source media="(min-width:650px)" srcset="https://pythonchannel.com/static/images/codecamp/img/srcset/M.jpg, https://pythonchannel.com/static/images/codecamp/img/srcset/L.jpg 2x">
                <source media="(min-width:420px)" srcset="https://pythonchannel.com/static/images/codecamp/img/srcset/S.jpg">
                <img src="https://pythonchannel.com/static/images/codecamp/img/srcset/L.jpg" alt="srcset" style="width:100%;">
              </picture>
              <hr>
              <p><a href="https://pythonchannel.com">by 町のWeb屋 大島</a></p>
            </article>
          </main>
        </body>
        </html>
    

グリッドレイアウトを手伝ってくれるFlex

image

ブラウザ上で要素を横や縦に並べたい時、あなたならどうやって並べますか? float、 table、 Bootstrap のグリッドシステム、いろいろあると思いますが、 CSS の Flex、シンプルで便利です。

iPhone SE のページでも、文字表示の部分やスマホ画像が回転する部分で flex-direction: column;flex-wrap: wrap; が使用。 flex-〇〇 とすることで、要素を縦でも横でも好きな方に並び替えられ、左寄せや中央寄せなどの制御も簡単。

要素の中央寄せ、というと CSS の

position: absolute;
position: relative;

が定番ですが、 flex による中央制御もシンプルでアリかも知れませんね。

参考までにシンプルな flex ページを作成してみましたので、よろしければご参照ください。

サンプルページ

上図のコードを今見る

        <!DOCTYPE html>
        <html lang="ja">
        <head>
          <meta charset="UTF-8" />
          <title>Flappy Bird</title>
          <meta name="viewport" content="width=device-width, user-scalable=no">
          <style>
            body{
              max-width:900px;
              margin:0 auto;
              padding: 1rem;
              text-align:center;
              background-color: #ccffff;
            }
            .flex-container {
              display: flex;
              justify-content: center;
              background-color: blue;
            }
            .flex-container > div {
              background-color: #f1f1f1;
              width: 100px;
              margin: 10px;
              text-align: center;
              line-height: 75px;
            }
            .flex-container-2 {
              display: flex;
              flex-direction: column;
              background-color: blue;
            }
            .flex-container-2 > div {
              background-color: #f1f1f1;
              width: 100px;
              text-align: center;
              line-height: 75px;
              margin: 10px auto;
            }
          </style>
        </head>
        <body>
          <main>
            <article>
              <div class="flex-container">
                <div>1</div>
                <div>2</div>
                <div>3</div>
              </div>
              <hr>
              <div class="flex-container-2">
                <div>1</div>
                <div>2</div>
                <div>3</div>
              </div>
              <hr>
              <p><a href="https://pythonchannel.com">by 町のWeb屋 大島</a></p>
            </article>
          </main>
        </body>
        </html>
    

ちなみによく似た CSS に Grid があります。画面幅に対して均等に表示してくれる CSS の Grid、一見すると flex と同じようにも思えますが、用途が異なります。 flex は1次元(縦方向か横方向)用に用意された CSS 機能に対して、Grid は2次元用(表)に用意された CSS 。flex でも2次元レイアウト可能ですが、基本的には1次元のレイアウトの時に flex 用いたいですね。

CSSアニメーションっぽいmatrix()

iPhone SE のページをスクロールダウンしていくと、次々にいろいろなアニメーションが起こります。この複雑な動きの制御、JavaScript と CSS の絶妙なハーモニーによって表現。

JavaScript の方は複雑なのでさておき、CSS側の制御を担当する matrix() について少しご紹介しますね。

matrix() 初めて聞く、という方もいらっしゃると思います。 matrix() は、 transformプロパティの一つで2次元の変形を可能にしてくれるもの。縦を伸ばしたり、横を伸ばしたり、または横や斜めに移動したり。そんな変幻自在そうな CSS 機能とスクロール位置を JavaScript でいい感じに制御して、iPhone SE を回転させたり、文字を上に動かしたりしている、というわけですね。

【matrix のサンプルコード】
transform: matrix(1, 0, 0, 1, 20, 0)

1番目の数値は、水平方向の縮尺
2番目の数値は、垂直方向の傾斜率
3番目の数値は、水平方向の傾斜率
4番目の数値は、垂直方向の縮尺
5番目の数値は、水平方向の移動距離
6番目の数値は、垂直方向の移動距離

image

上図のコードを今見る

        <!DOCTYPE html>
        <html>
        <head>
            <style>
                div {
                    width: 100px;
                    height: 100px;
                    background-color: green;
                }
                div#my-matrix1 {
                    transform: matrix(1, 0, 0, 1, 20, 0); 
                }
                div#my-matrix2 {
                    transform: matrix(0.8, 0, 0, 1, 150, 0); 
                }
            </style>
        </head>
        <body>
            <div id="my-matrix1"></div>
            <div id="my-matrix2"></div>
        </body>
        </html>
    

matrix を使った例をみても、ちょっと iPhone SE の Webページには程遠い感じがしますよね。

しかし、この matrix() の値を JavaScript で動的に変更してみると下図のように。

サンプルページ

上図のコードを今見る

        <!DOCTYPE html>
        <head>
          <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
           
          <style>
            body{
              max-width:900px;
              margin:0 auto;
              padding: 1rem;
            }
            #scroll-box {
              overflow: scroll;
              height: 30vh;
              border: 1px solid black;
            }
            #scroll-contents {
              height: 150vh;
            }
            #box{
              width: 100px;
              height: 100px;
              background-color: yellow;
              transform: matrix(1, 0, 0, 1, 0, 0)
            }
          </style>
           
        </head>
         
        <body>
          <main>
            <article>
              <div id="scroll-box">
                <div id="scroll-contents">スクロール領域
                  <div id="box"></div>
                </div>
              </div>
              <hr>
              <p><a href="https://pythonchannel.com">by 町のWeb屋 大島</a></p>
            </article>
          </main>
          <script>
            $('#scroll-box').scroll(function() {
              var a =  $(this).scrollTop();
              console.log(a);
              var anime = "matrix(1, 0, 0, 1, " + a + ", " + a + ")";
              console.log(anime);
              $('#box').css("transform", anime);
            });
          </script>
        </body> 
        </html>
    

こんな風にスクロールに合わせて matrix() の値を変えてあげると、 iPhone SE ページのようにスクロールに合わせて画像を動かすことが可能に。

一般的にはこうした JavaScript の処理、 canvas タグを用いているケースが一般的ですが、CSS で動きを制御することで多様な端末に対応しやすい特徴があるでしょう。

一流デザイナーのスキルが身に付く

CodeCampの無料体験はこちら

まとめ

iPhone SEのページ、今回ご紹介した wbr や flex 意外にも、 sticky や OGP など、 Web 開発初心者にとっては教科書に載っていないことが盛り沢山です。

「あのサイトのデザインのここをマネしたいんだけどな... HTML コードがわからない」「あのサイトのあの動き、いいな、でも JavaScript が???」という方、その問題は HTML や CSS、 JavaScript の基礎をクリアすれば恐らく解決できるのではないでしょうか?

日進月歩で進化を続ける Webテクノロジー、スピードを上げてスキルを習得するには、プログラミングスクールが最適ではないでしょうか?

まずは CodeCamp の無料体験レッスン、検討してみませんか?

関連記事

オシママサラ
この記事を書いた人
オシママサラ
\ 無料体験開催中!/自分のペースで確実に習得!
オンライン・プログラミングレッスンNo.1のCodeCamp