20200329のCSSに関する記事は7件です。

読みやすいコードを書きたい!

この記事の趣旨

 自分の学習のメモとして残します。
 どなたかのお役に立てたら光栄です。

こんな方におすすめです

 ・コードが見づらいと言われる
 ・初心に返りたい
 このような方には何か発見があると思います。

読みやすいコードとは?

 ズバリ『良いコード』のこと。
 良いコードは、他人がそのコードを見た時に短時間で理解できるコードのことを言います。

 逆に、分かりづらい・理解しづらいコードは解読に時間がかかります。それだけ開発の工数もかかってしまい、効率が良くありません。

 では、良いコードの条件・要素を紐解いていきましょう!

●コードの命名に規則を

 変数やメソッドは好きなように命名ができます。
 ルールがありませんので、個人の好きなようにできます。
 特に共同開発の現場などでは、「他人が見てわかる」を意識する必要があります。

 ◎命名のポイント

  【目的がわかる単語を使う】
    例)new → new_account

  【汎用的な名前は避ける】
   ・一時的な変数などは避ける
   ・可読性を意識して

  【名前に情報を含める】
   大文字、小文字をルールに沿って活用
 
  【誤解されない名前を使う】
   ・何がしたいかが明確な名前
   ・説明的に長くなっても良いので、可読性重視
     例)read_books → already_read_books

●コードレイアウト

 プログラムの挙動に影響はないが、可読性を大幅にあげることができる

 ◎レイアウトのポイント

   ・整列    :縦列を揃える。イコールの位置など縦が揃うと見やすい
   ・一貫性   :似たような構造は同じフォーマットに統一できないか検討
   ・ブロック化 :同じ系統の変数などをまとめてグループ化すること

●コメント

 ・プログラムの動作を説明
 ・他の開発者がコードを読む際の理解を助ける
  ※多すぎても読むのに時間がかかるため、簡潔に

 ◎コメントのポイント

   ・理由をコメントする  :なぜそのコードを書いたか
   ・他の開発者へメモを残す:開発中のメモとして
   ・実際の例を記入する  :コメントでは伝わりづらい時は、コメントとしてコードを記載

まとめ

 結局大事なことは
  「人に対する思いやり」だなぁと。

 複数人で仕事をする以上、「自分だけ良ければそれで良い」という考えはNG。
 誰もが見やすく、仕事をしやすい状況を自分が作り出す意識が大切。

 そのための知識や技術であると思う。

 これからしっかり学んでいきましょう。

   

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Sassでfor文を使ったページローダーのようなものを作る方法

はじめに

Sass記法にはなんとfor文も存在するということで、どういう使い方をするのか一例としてページローダーのようなものをCSSで表現してみたいと思います。
Sassでは他にもif文なんかも使えます。

Sassと言ってますが、基本的にはscss記法で書いていきます。そちらの方が個人的には見やすいので。

この記事ではSassについての詳しい解説は行いません。

ちなみに

SassMeisterというサイトで、CSSにコンパイルされた記述も同時に見ながらコードを書くことができるので、サクッと書いてみたい場合はこちらが便利です。
スクリーンショット 2020-03-29 16.56.52.png
左のSassのスペースにSassまたはscss記法で書いていくと、CSSのスペースに表示されます。

Sassのfor文の記載方法

基本的な書き方

scss
@for $i from 1 through 5 {
  nth-child(#{$i}) {
    animation-delay: -0.3s / $i ;
  }
}

@forでfor文の宣言をし、$iで可変する数字部分の変数宣言を行います。ここまでは一般的なfor文とほぼ変わりません。
from 1through 5で1〜5までをループするという意味になります。
で、そのnth-child()のカッコ内に変数宣言をした$iを入れてあげます。
セレクター内や、文字列内に変数を使う場合#{}で変数を囲む必要があります。
プロパティの値にその変数を使用する場合はそのまま使えます。

scss
@for $i from 1 to 5 {
  nth-child(#{$i}) {
    animation-delay: -0.3s / $i ;
  }
}

ちなみにfrom 1to 5という書き方をすることもでき、こちらは5を抜いた1〜4までという意味になります。

ページローダーっぽいやつの作り方

Sassのfor文と、animationプロパティを用いて作っていきます。

さっそくですが、こんな感じのやつです。

See the Pen oNXJRPr by fumu (@fumu238) on CodePen.

以下、簡単な解説。

html
<div class="three-dot">
    <div></div>
    <div></div>
    <div></div>
    <div></div>
</div>

htmlは特になんてことないですね。ローダー部分の要素となるdivを4つ作り、親要素の中に入れておきます。

scss
.three-dot {
    text-align: center;

    & div{
        display: inline-block;
        width: 18px;
        height: 18px;
        background-color: black;
        border-radius: 50%; 
        animation-name: delay;
        animation-duration: 1.4s;
        animation-iteration-count: infinite;
    }
}

まず4つの子要素をdisplay:inline-blockで横並びにし、黒い●状にします。
これにあとは動きをつけるために

scss
@keyframes delay {
    0% {
        transform: scale(0);
    }
    40% {
        transform: scale(1);
    }
    80% {
        transform: scale(0);
    }
    100% {
        transform: scale(0);
    }
}

@keyframesを使用して指定をしていきます。0%〜100%までの中でどような変化をするか%を指定して細かく指定できます。
ここではtransform:scale()を用いて0%~40%で開いて、あとは閉じる。みたいな動きにします。

animation-name@keyframesの名前を指定し、animatino-durationで何秒かけてその動作を行うか指定し、animation-iteration-count: infinite;でそれを無限に行うように指定します。

See the Pen eYNbwvX by fumu (@fumu238) on CodePen.

そうすると、この段階では4つの●が同時にちっちゃくなったり大きくなったりします。
ここでfor文の出番です。

scss
.three-dot {
    text-align: center;

    & div{
        display: inline-block;
        width: 18px;
        height: 18px;
        background-color: black;
        border-radius: 50%; 
        animation-name: delay;
        animation-duration: 1.4s;
        animation-iteration-count: infinite;

        @for $i from 1 through 3 {
            &:nth-child(#{$i}) {
                animation-delay: -0.4s + $i * 0.1;
            }
        }
    }
}

子要素のdivのn番目にそれぞれCSSを追加するための:nth-childでfor文を作ります。
今回は4つdivがあるので、その1〜3つめにanimation-delayをマイナスの値で設定します。マイナスでdelayを設定すると、delayせずむしろ早く変化を始めることになります。
そしてその設定した値を変数を使って計算すると

ループの1回目は-0.4s + 1 * 0.1 = -0.3s
ループの2回目は-0.4s + 2 * 0.1 = -0.2s ...

となり、数が増えるたびに値が変わっていくことになります。

CSSにコンパイルされるとこう。

css
nth-child(1) {
    animation-delay: -0.3s;
}
nth-child(2) {
    animation-delay: -0.2s;
}
nth-child(3) {
    animation-delay: -0.1s;
}

これで0.1秒ごとに変化をつけることができるようになり、見本のような動きになります。

ちなみに。for文の中で計算を行いましたが、Sassで四則演算を行うときには単位を気にせず計算することができます。
pxなんかも単位をつけたまま計算することができるので、余計な事を考えなくて済みますね。

おわりに

以上、Saasでfor文を使ったページローダーっぽいものの作り方でした。
他にもtransformを使って回転させたり、丸ではなく四角で作ったり、要素を重ねたりと、いろんなパターンが作れそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

親要素の中で子要素をそれぞれ左寄せと右寄せに

親要素に対して
display: flex;
justify-content: space-between;

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CSSのプロパティを自動で並べ替える方法

複数人で開発をしていると

  • marginとpaddingってどちらを先に書けば良いだろう?
  • position指定ってtop -> right -> bottom -> leftの順が良いのかな?

などの話が出ることはありませんか?

自分は結構質問されるのですが、個人的にはカスケーディングがスタイルに影響を与えない場面ではどんな順番でも良いと思っています。

しかし、ルールがあればミスが減り、レビューがしやすくなるのも事実。

というわけで自動でプロパティの並び順を変更できる設定を作っていきましょう。

Prettierのインストール

yarn add prettier -D

まず初めにPrettierをインストールします。
Prettierはコードフォーマッターで、予め指定したルールに沿ってコードを整形してくれます。

stylelintのインストール

yarn add stylelint -D

次にstylelintをインストールします。
stylelintはリンターで、CSSやSCSSなどのエラー回避や書式の統一に役立ちます。

stylelint-config-prettierのインストールと設定

yarn add stylelint-config-prettier -D
.stylelintrc
{
  "extends": ["stylelint-config-prettier"]
}

stylelint-config-prettierはPrettierと競合するルールをオフにしてくれます。
ルールが競合するとお互いがお互いをエラー/書式のミスとして認識しておかしなことになってしまうためインストールが必要です。

stylelint-prettierのインストールと設定

yarn add stylelint-prettier -D
.stylelintrc
{
  "extends": ["stylelint-config-prettier"],
  "plugins": ["stylelint-prettier"],
  "rules": {
    "prettier/prettier": true
  }
}

stylelint-prettierはPrettierをstylelintのルールとして実行し、エラーを教えてくれたり修正したりに使います。
.stylelintrcの中でプラグインの有効化とルールの追加をします。

なお、stylelint-prettierをインストールしたからとPrettierやstylelintが自動でインストールされるわけではありません。
そのため前の項で手動でインストールを行っています。

また、上記の.stylelintrcは実は次のように短く書けます。

.stylelintrc
{
  "extends": ["stylelint-prettier/recommended"]
}

stylelint-prettier/recommended

  1. stylelint-config-prettierをextend
  2. stylelint-prettierプラグインを有効化
  3. prettier/prettierルールを有効化

してくれるためです。

stylelint-orderのインストールと設定

yarn add stylelint-order -D
.stylelintrc
{
  "extends": ["stylelint-prettier/recommended"],
  "plugins": ["stylelint-order"],
  "rules": {
    "order/properties-alphabetical-order": true
  }
}

stylelint-orderはその名の通りプロパティの並び順ルールについてのパッケージです。
並び順は色々なルールがあるようですが、自分は一番明快だろうとアルファベット順を選択しました。

準備完了、あとはコマンドを叩くだけ

yarn run stylelint '**/*.css' --fix

上記のようなコマンドを叩くとCSSの並び順を修正してくれます。
'**/*.css'の部分はこの書き方だと全てのCSSファイルへの修正が走りますが、具体的に'src/style/somepage.css'のようにしてもOKです。

補足

実際にstylelintを使う場面ではほぼ間違いなくstylelint-config-standardなど土台となるルールセットも一緒に使うと思いますが今回は割愛しています。

リンク一覧

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【曖昧さ回避】ブラウザレンダリングにおける「ファイルの読み込み」が意味するものとは

「ファイルの読み込み」とは

ブラウザレンダリングの仕組みを解説するサイトや書籍には、「ファイルを読み込んで〜」のような説明が多くあります。
自分がレンダリング工程を勉強しているときに、この「読み込み」という言葉がファイルのDownload(転送)を指すのか、ファイルのParse(解析)を指すのか、はたまたレンダリング全体のことを言っているのか、説明する場面によって意味が変わる曖昧な言葉だなーと感じていました。

ここではブラウザレンダリングの仕組みについて、1.HTMLのみ、2.HTMLとCSS、3.HTMLとJavaScript、4.HTMLとCSSとJavaScriptの4パターンに分けて、レンダリングフローに定義された言葉に当てはめながら説明していきたいと思います。

(検証環境:Google Chrome バージョン: 80.0.3987.87)

ブラウザレンダリングの仕組みの大枠

ブラウザレンダリングのフローは大きく4つの工程に分けられ、それぞれの工程は更にいくつかの細かい工程に分けられます。
(参考:Webフロントエンド ハイパフォーマンス チューニング -久保田 光則 (著)
ブラウザレンダリングの流れ.png

  • Loading(データのダウンロード・解析)
    • Download
    • Parse
  • Scripting(JSの実行)
  • Rendering(スタイルの計算、当て込み)
    • Calculate Style
    • Layout
  • Painting(描画)
    • Paint
    • Rasterize
    • Composite Layers

図を見ていると全ての工程がシリアル(直列)に進んでいくように誤解しやすいのですが、実際はそうではありません。
レンダリングエンジンがページ表示を最適化する中で、部分的にでも準備ができた段階で、都度次の工程に進むこともあります。

本記事では主にLoading(Download、Parse)Scriptingの工程に関して、ファイルごとにどのように影響を及ぼし合い、レンダリングの処理順が決まっているかについて説明します。

RenderingPaintingの工程を含むブラウザレンダリング全体の仕組みについては以下記事が詳しいです。
フロントエンジニアなら知っておきたいブラウザレンダリングの仕組みをわかりやすく解説! | LeapIn

1.HTMLのみ

はじめに外部ファイル「読み込み」記述が一切ない純粋なHTMLファイルについて、
ブラウザ検索バーにURLを入力し、HTTPプロトコルで通信してページを表示する場合を考えます。
(参考:ネットワークやTCP/IPやHTTPの基本(初学者向け) - Qiita

レンダリングの工程としては、まずHTMLDownloadが始まりますが、
ここでのポイントは、サーバからHTMLファイルなどのリソースが転送される手法は0か1の転送ではなく、
セグメントに分割しながら転送されるということです。
(どのくらいまとめて送るのかについてはサーバサイドで制御するようです)

前提として、ブラウザはUX向上のため画面に何も表示されていない時間を短くするように動きます。
よって全てのHTMLDownloadが完了していなくても、転送されたHTMLセグメントを元にParse(DOMツリー構築)や後続の処理が進み、準備ができたDOMから画面描画が始まります。

スクリーンショット 2020-03-29 2.12.07.png
上記はChrome DevToolsのNetworkパネルであり、一つのHTMLファイルをダウンロード完了するまでの解析図です。(テスト用にサーバサイド(PHP)でファイルの転送や解析速度を調整しています)

Waiting(TTFB:Time To First Byte)とはファイル転送リクエストを送ってからクライアント側で最初のデータを受け取るまでにかかる時間(主にサーバサイドの処理時間)であり、Content Downloadとは最初のデータを受け取ってから全てのデータを受け取りきるまでにかかる時間です。

解析グラフによるとContent Downloadに合計2sかかっていますが、その間も転送されてきているデータを元に別の処理(Parse、Rendering、Painting)が都度進んで描画が始まっており、それは同Performanceパネルで解析することができます。↓
スクリーンショット 2020-03-29 19.13.47のコピー.png
データを受け取る(Receive Data)たびに、HTMLParse(DOM構築)のフェーズを経て、Composite Layersまでの描画工程を完了していることが分かります。

このように準備ができたところから都度描画が行われることで、First Paint(画面に最初になにかしらが描画されタイミング)や、First Meaningful Paint(画面に最初にユーザーに意味のある表示がされたタイミング)などの表示タイミング差が存在します。

参考:Ace the Lighthouse Audit: Best Practices for Consistent Interactivity | Lumavate

2.HTMLとCSS

head要素の中のlink要素に外部CSS「読み込み」記述がある場合を考えます。

HTML
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <!-- bodyの中身 -->
  </body>
</html>

CSSのDownload

この場合も、まずHTMLDownload、Parseが始まり、解析途中でlink要素を見つけた段階でCSSDownloadが始まります。↓
スクリーンショット 2020-03-29 14.07.42.png
CSSのDownloadはHTMLのParseをブロックしないので、CSSDownload中もHTMLParseが並行して進みます。
そしてその先に再び外部CSS「読み込み」記述ががあれば、同時に複数のCSSDownloadが始まります。

ただし、モダンブラウザでは(同じドメインの)TCP接続は同時に6本までという制限があるため、7本目以降の接続は前の接続の終了を待ってからとなります。
スクリーンショット 2020-03-29 14.45.11のコピー.png
見ての通りこれではダウンロードしたいファイルが多いほどページ表示速度が遅くなってしまいます。

そのため、対応策としてファイルを可能な限りまとめてリクエスト必要数を抑えたり、CDNなどを利用してあえて別ドメインから接続することでスループットを上げたり、一つのTCP接続で同時に複数のリクエスト/レスポンスを処理できるhttp/2プロトコルで通信するなどの手法が存在します。

参考:そろそろ知っておきたいHTTP/2の話 - Qiita

CSSのParse

CSSもHTMLと同様にDownloadの次の工程として、Parse(CSSOMの構築)の工程があります。
考慮すべき注意点は以下です。

  • CSSParseは見かけ上はHTMLParseと並行して行われる。
  • HTMLは描画工程に進もうとするDOMの、直前までに記載されているCSSのLoading(Download、Parse)が完了しない限り、Renderingフローに進まない。(描画処理が行われない)

HTMLParseCSSParseはどちらもレンダリングエンジンのmainスレッドで行われますが、mainスレッドでは同時に一つの処理しか行えないため、それぞれの処理が同時に走ることはありません。
ですが、HTMLParseのアイドル時間などにCSSParseが進むため、見かけ上は2つが並行して行われているように見えます。
(そもそもCSSParseにかかる時間はブラウザレンダリング全体の時間からすると極めて短く、議論に上がりにくい部分のようです。)

また、CSSのLoadingが進行中の場合は、たとえHTMLParseが先に完了していてもRenderingなどの次の工程に進まず、結果として画面描画が行われません。

これはブラウザがFOUCFlash of Unstyled Contentの略。スタイルがついていないコンテンツが一瞬表示されること)を防ぐために、CSSParseの完了を待ってスタイルが適応された画面描画を行おうとするためです。
スクリーンショット 2020-03-29 15.35.54のコピー.png
上記Performanceパネル解析図を見ても、Finish LoadingCSSParseの完了)まで、Calculate StyleなどのRendering工程に進んでいない(画面描画が行われていない)ことが分かります。

3.HTMLとJavaScript

以下のようにhead要素の中にscript要素を記述して、外部JavaScriptファイルを「読み込む」場合を考えます。

HTML
<!DOCTYPE html>
<html>
  <head>
    <script src="main.js"></script>
  </head>
  <body>
    <!-- bodyの中身 -->
  </body>
</html>

JSのDownloadとScripting

HTMLParseが始まってscript要素に到達するとJSのDownloadが始まります。
その時に重要なポイントが、JSのDownloadとScripting(実行)はHTMLParseをブロックするということです。

一度JSのDownloadが始まると、ダウンロードしたJSのScripting工程が完了しない限り、それ以降のHTMLParseが行われません。
これが、JSの記述はbodyの最後に記述するべきと言われる理由の一つです。
スクリーンショット 2020-03-29 20.29.02のコピー.png
上記図より、Send RequestJSDownloadが始まると、Evaluate Script工程が完了するまでHTMLParseが行われていないことが分かります。

async属性とdefer属性

script要素によるJSの「読み込み」記述はそれ以降のHTMLParseをブロックしますが、script要素asyncdeferの属性をつけることによってJSのDownloadを非同期に行い、HTMLParseと同時に処理することができます。

HTML
<script src="main.js" async ></script>

<!-- もしくは -->

<script src="main.js" defer ></script>

以下は先程と同じ記述で、defer属性を使用したときのPerformanceパネルの解析結果です。
スクリーンショット 2020-03-29 20.34.04のコピー.png
JSのDownloadが開始(send Request)しても、HTMLParseがブロックされずに先の工程に進み、最終的にComposite Layersまで完了して画面描画が行われているのが分かります。
その後JSのDownloadが完了した段階で、Scripting(Evaluate Script)処理が行われています。

参考:scriptタグに async / defer を付けた場合のタイミング - Qiita

4.HTMLとCSSとJavaScript

CSSとJavaScriptの両方の「読み込み」記述を書く場合です。
以下のようにlink要素の直下にscript要素を入れてみます。

HTML
<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="style.css" />
    <script src="main.js"></script>
  </head>
  <body>
    <!-- bodyの中身 -->
  </body>
</html>

CSSDownloadHTMLParseをブロックしないため、HTMLParsescript要素の記述に到達しJSのDownloadが始まります。
先程「HTMLは直前までのCSSLoading(Download、Parse)が完了していない限り、Renderingフローに進まない」と説明しましたが、実は同様にJSも直前までのCSSLoading(Download、Parse)が完了していない限り、Scriptingの工程に進まない性質があります。

つまりこの場合、CSSよりもJSのほうが速くDownloadが完了したとしても、CSSParseが完了するまでScriptingが待機状態になるということです。
スクリーンショット 2020-03-29 16.35.27のコピー.png
↑JSのほうがCSSよりも1s速くDownloadが完了していますが、
スクリーンショット 2020-03-29 16.34.37のコピー2.png
↑CSSのLoading(Download、Parse)完了を待ってから、Scripting(Evaluate Script)処理が実行されていることが分かります。

参考:DOMContentLoaded周りの処理を詳しく調べてみました - Qiita

ブラウザのプリロード機能

以下のようにJSの「読み込み」記述をCSSよりも前に書いた場合を考えます。

HTML
<!DOCTYPE html>
<html>
  <head>
    <script src="main.js"></script>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <!-- bodyの中身 -->
  </body>
</html>

defer属性async属性がついていないscript要素による外部JSファイルの「読み込み」なので、JSのDownload、Scriptingが完了するまでそれ以下のHTMLParseが進まない、つまりCSSDownloadも進まないはずです。

しかし、モダンブラウザではその限りではありません。
NetWorkパネルを見てみると、JSとCSSのDownloadが同時に行われていることが分かります。
スクリーンショット 2020-03-29 21.22.31のコピー.png
実はChromeなどのモダンブラウザには、HTMLParseが進んでいない部分についてもDownloadが必要な記述がないか確認し、もしあれば事前にそのファイルのDownloadを開始する機能があります。(Preload Scanner

よってこの場合も、ブラウザはJSのDownload中にその先にあるCSSの「読み込み」記述を読み取り、CSSDownloadも同時に進めることでレンダリングを高速化しているのです。

※Preload Scanner機能で事前処理できるのはDownloadの工程だけです。ParseScriptingの工程は本来のレンダリングフローに沿って行われます。

参考:rel="preload"を極めるために必要な2種類のプリロード機能 | Raccoon Tech Blog

まとめ

  • HTMLはセグメントごとにDownloadが行われ、都度Parseなどの先の工程に進む
  • CSSのDownloadHTMLのParseをブロックしない
  • CSSのParseは見かけ上はHTMLParseと並行して行われる
  • HTMLは直前までのCSSLoading(Download、Parse)が完了していない限り、Renderingの工程に進まない
  • JSのDownloadScripting(実行)HTMLのParseをブロックする
  • JSも直前までのCSSLoading(Download、Parse)が完了しない限り、Scriptingの工程に進まない

誤った解釈等ございましたら、ご教授お願いいたします。。

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【CSS & JS】超簡単。ハンバーガーをクリックで×に変える&メニューをスライドアウトさせる方法

備忘録です。

ハンバーガーメニューをクリックすると、×印に変えるのってどうやるんだろう〜CSSでつくる方法もあるらしいけど、どうやるんだろう。密かにずっと気になっていたので調べてみました。

JavaScriptも使いますが、決してややこしいことはしなくていい方法を見つけました。

ここでは二つのことをします。
❶ハンバーガーにクリックすることで×印に変える
❷メニューを画面の右側からスライドアウトさせる。

まずはHTMLから。

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="css/styles.css" />
    <script
      src="https://code.jquery.com/jquery-3.4.1.min.js"
      integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
      crossorigin="anonymous"
    ></script>
    <title>Slide Out Menu</title>
  </head>
  <body>
    <header>
      <nav>
        <div class="burger-menu-icon">//①ハンバーガーのdivをつくる
          <input type="checkbox" id="burger" />//②Toggleするためにはcheckboxを書く!ここがカギ!
          <label for="burger">//③label forはinputのidとそろえる。
            <div class="burger-icon">
              <span></span>
              <span></span>
              <span></span>
            </div>//④labelのなかにハンバーガーアイコンを入れましょう。
          </label>
          <div class="slideoutMenu">//⑤スライドアウトさせるメニューは、burger-menu-iconのdiv内におさめます。
            <div class="opacity"></div>
            <div class="menu">
              <ul>
                <li><a href="#">Home</a></li>
                <li><a href="#">About</a></li>
                <li><a href="#">Contact</a></li>
                <li><a href="#">Design</a></li>
                <li><a href="#">Style</a></li>
                <li><a href="#">Reviews</a></li>
              </ul>
            </div>
          </div>
        </div>
      </nav>
    </header>
    <script src="script.js"></script>
  </body>
</html>

ポイント❶
toggleするにはinput type="checkbox"を使う

ポイント❷
今回はハンバーガーアイコンをクリックすることで、メニューを引っ張り出したいです。なのでハンバーガーアイコンは、<label for="burger"></label>のなかに入れましょう。通常であればcheckboxをチェックしなければ、checkboxにチェックはつきませんが、label forというものを付け加えると、label forの中身をクリックするだけでcheckboxにcheckがつけられます。ただし一点。label for="burger"と、input id="burger"labelをinputと紐づけるには、この二つをそろえる必要があります。inputは必ずidで指定します。

ポイント❸
ハンバーガーアイコンと隠しているメニューは、同じdiv内に入れる。(この場合は.burger-menu-icon

SCSS

.burger-icon {
  display: block;
  z-index: 11;
}

.burger-icon span { //ここでburger-iconをつくる
  display: block;
  background: #000; //background-colorではなく、backgroundで指定
  width: 50px;
  height: 5px;
  margin-bottom: 10px;
  margin-left: 90%;
  cursor: pointer;
  position: relative;
  top: 0;
}

input#burger { //labelここでcheckboxを消す
  display: none;
}

.burger-icon.open span:nth-child(2) { //クリックすると'open'というクラスがtoggleされるよう、JSに記述しています。つまり、これはハンバーガーをクリックするとハンバーガーの2本目の線が消えるという記述です。
  width: 0;
  opacity: 0;
}

.burger-icon.open span:nth-child(1) { //これはハンバーガーをクリックするとハンバーガーの1本目の線が45度回転し、上から15px下方向にずらすという記述です。
  transform: rotate(45deg);
  top: 15px;
}

.burger-icon.open span:nth-child(3) {//これはハンバーガーをクリックするとハンバーガーの3本目の線が-45度回転し、15px上方向にずらすという記述です。
  transform: rotate(-45deg);
  top: -15px;
}

.slideoutMenu {
  transform: translateX(100%); //メニューを右に100%ずらすことで、画面から消す。
  z-index: -1;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  transition: 0.3s;
  animation: slideOut 0.3s;
  .opacity,
  .menu {
    width: 50%;
    background-color: #5d348c;
    ul {
      list-style: none;
      li {
        padding-bottom: 3rem;
      }
      li a {
        text-decoration: none;
        font-size: 3rem;
        color: #ea5c5d;
        text-transform: uppercase;
      }
    }
  }
  .opacity {
    background-color: #ea5c5d;
    opacity: 0.7;
  }
}

@keyframes slideOut { //ここでスライドの動作をつくります。(slideIn、のほうがふさわしかったかも T_T )
  0% {
    transform: translateX(100%);
  }
  50% {
    transform: translatex(50%);
  }
  50% {
    transform: translatex(0%);
  }
}

input:checked ~ .slideoutMenu { //これがツワモノ!!!詳細は【覚えておきたいポイント3】で。
  transform: translateX(0%);
}

覚えておきたいポイント❶
<input>タグのあとに<label for="burger">を付け足しておけば、labelタグ内の要素をクリックすることでcheckboxをチェックできるようになります。

覚えたいおきたいポイント❷
.burger-icon.open span:nth-child(3), .burger-icon.open span:nth-child(1)ではハンバーガーの上の線と下の線を回転させ、top:〜で位置をずらしています。topの位置をずらすには、.burger-icon spanposition: relative; top: 0;と書かないと効かないので注意です。

覚えたいおきたいポイント❸
最後にあるinput:checked ~ .slideoutMenuを書くことで、メニューが右側から画面にスライドインしてくれます。
input:checkedは、「チェックボックスがcheckされていたら……」という意味です。~は、兄弟要素を取得したいよ〜という意味合いを持つ記号です。input.slideoutMenuはどちらともburger-menu-iconの子要素なので、兄弟要素に値します。~がないと効かないので注意です。

JS

$(".burger-icon").click(function() {
  $(this).toggleClass("open");
});

JSではシンプルに、「.burger-iconのクリックで、openというclassをtoggleしてね」と伝えているだけです。

地味に時間がかかりますが、、一番わかりやすいかなと感じました。こんなに簡単に実装できるとは!animationがわかると、CSSは一層おもしろみが増す気がします。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【CSS & JS】超簡単。ハンバーガーアイコンをクリックして×に変える&メニューをスライドアウトさせる方法

備忘録です。

ハンバーガーメニューをクリックすると、×印に変えるには……CSSでつくる方法もあるらしいけど、どうやるんだろう。密かにずっと気になっていたので調べてみました。

JavaScriptも使いますが、決してややこしいことはしなくていい方法を見つけました。

ここでは二つのことをします。
❶ハンバーガーにクリックすることで×印に変える
❷メニューを画面の右側からスライドアウトさせる

まずはHTMLから。

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <link rel="stylesheet" href="css/styles.css" />
    <script
      src="https://code.jquery.com/jquery-3.4.1.min.js"
      integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
      crossorigin="anonymous"
    ></script>
    <title>Slide Out Menu</title>
  </head>
  <body>
    <header>
      <nav>
        <div class="burger-menu-icon">//①ハンバーガーのdivをつくる
          <input type="checkbox" id="burger" />//②Toggleするためにはcheckboxを書く!ここがカギ!
          <label for="burger">//③label forはinputのidとそろえる。
            <div class="burger-icon">
              <span></span>
              <span></span>
              <span></span>
            </div>//④labelのなかにハンバーガーアイコンを入れましょう。
          </label>
          <div class="slideoutMenu">//⑤スライドアウトさせるメニューは、.burger-menu-iconのdiv内におさめます。
            <div class="opacity"></div>
            <div class="menu">
              <ul>
                <li><a href="#">Home</a></li>
                <li><a href="#">About</a></li>
                <li><a href="#">Contact</a></li>
                <li><a href="#">Design</a></li>
                <li><a href="#">Style</a></li>
                <li><a href="#">Reviews</a></li>
              </ul>
            </div>
          </div>
        </div>
      </nav>
    </header>
    <script src="script.js"></script>
  </body>
</html>

ポイント❶

toggleするにはinput type="checkbox"を使う

ポイント❷

今回はハンバーガーアイコンをクリックすることで、メニューを引っ張り出したいです。なのでハンバーガーアイコンは、<label for="burger"></label>のなかに入れましょう。通常であればcheckboxをチェックしなければ、checkboxにチェックはつきませんが、label forというものを付け加えると、label forの中身をクリックするだけでcheckboxにcheckがつけられます。ただしlabel for="burger"と、input id="burger"labelをinputと紐づけるには、この二つをそろえる必要があります。inputは必ずidで指定します。

ポイント❸

ハンバーガーアイコンと隠しているメニューは、同じdiv内に入れる。(この場合は.burger-menu-icon

SCSS

.burger-icon {
  display: block;
  z-index: 11;
}

.burger-icon span { //ここでburger-iconをつくる
  display: block;
  background: #000; //background-colorではなく、backgroundで指定
  width: 50px;
  height: 5px;
  margin-bottom: 10px;
  margin-left: 90%;
  cursor: pointer;
  position: relative;
  top: 0;
}

input#burger { //labelここでcheckboxを消す
  display: none;
}

.burger-icon.open span:nth-child(2) { //クリックすると'open'というクラスがtoggleされるよう、JSに記述しています。つまり、これはハンバーガーをクリックするとハンバーガーの2本目の線が消えるという記述です。
  width: 0;
  opacity: 0;
}

.burger-icon.open span:nth-child(1) { //これはハンバーガーをクリックするとハンバーガーの1本目の線が45度回転し、上から15px下方向にずらすという記述です。
  transform: rotate(45deg);
  top: 15px;
}

.burger-icon.open span:nth-child(3) {//これはハンバーガーをクリックするとハンバーガーの3本目の線が-45度回転し、15px上方向にずらすという記述です。
  transform: rotate(-45deg);
  top: -15px;
}

.slideoutMenu {
  transform: translateX(100%); //メニューを右に100%ずらすことで、画面から消す。
  z-index: -1;
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  transition: 0.3s;
  animation: slideOut 0.3s;
  .opacity,
  .menu {
    width: 50%;
    background-color: #5d348c;
    ul {
      list-style: none;
      li {
        padding-bottom: 3rem;
      }
      li a {
        text-decoration: none;
        font-size: 3rem;
        color: #ea5c5d;
        text-transform: uppercase;
      }
    }
  }
  .opacity {
    background-color: #ea5c5d;
    opacity: 0.7;
  }
}

@keyframes slideOut { //ここでスライドの動作をつくります。(slideIn、のほうがふさわしかったかも T_T )
  0% {
    transform: translateX(100%);
  }
  50% {
    transform: translatex(50%);
  }
  50% {
    transform: translatex(0%);
  }
}

input:checked ~ .slideoutMenu { //これがツワモノ!!!詳細は【覚えておきたいポイント3】で。
  transform: translateX(0%);
}

覚えておきたいポイント❶

<input>タグのあとに<label for="burger">を付け足しておけば、labelタグ内の要素をクリックすることでcheckboxをチェックできるようになります。

覚えたいおきたいポイント❷

.burger-icon.open span:nth-child(3), .burger-icon.open span:nth-child(1)ではハンバーガーの上の線と下の線を回転させ、top:〜で位置をずらしています。topの位置をずらすには、.burger-icon spanposition: relative; top: 0;と書かないと効かないので注意です。

覚えたいおきたいポイント❸

最後にあるinput:checked ~ .slideoutMenuを書くことで、メニューが右側から画面にスライドインしてくれます。
input:checkedは、「チェックボックスがcheckされていたら……」という意味です。~は、兄弟要素を取得したいよ〜という意味合いを持つ記号です。input.slideoutMenuはどちらともburger-menu-iconの子要素なので、兄弟要素に値します。~がないと効かないので注意です。

JS

$(".burger-icon").click(function() {
  $(this).toggleClass("open");
});

JSではシンプルに、「.burger-iconのクリックで、openというclassをtoggleしてね」と伝えているだけです。

やりかたは何通りもあると思うのですが、個人的にはこれが一番わかりやすいかなと感じました。

完成版のgif?
Screen Recording 2020-03-29 at 04.31 PM.gif

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む