CSSを習得せずにWebレイアウトを習得することは、乾燥した土地で泳ぐことを学ぶのとほぼ同じくらい実現可能です。しかし、一度習得すると一生残るスキルである水泳とは異なり、CSSの習得は、CSS自体が絶えず進化しているため、実際には終わらないプロセスです。
この課題は、異なるブラウザー間(および同じブラウザーの異なるバージョン間でも)のCSS実装とサポートの違い、およびCSS推奨の採用率の違いによって悪化します。 10年以上もの間、Webデザイナーと開発者は、散発的で一貫性のない追加のバーストに取り組んできました。 サポートされているCSS3機能 新しいブラウザのバージョンごとに。
しかし、それはそうかもしれませんが、 CSSをマスターする どんな固体にとっても絶対に必要なものです Webデザイナーまたは開発者 。この記事では、従来のCSS2手法からCSS3の最新のレイアウトアプローチまで、いくつかの基本的なCSSレイアウトの原則について説明します。
注意: この記事のすべてのコードサンプルは HTML5 要素と サス 構文。完全に機能するコードは、 https://github.com/laureanoarcanio/css-layout-examples 。
テクノロジーを学ぶための最良の方法の1つは、サポートしようとしている特定のユースケースまたは解決しようとしている特定の問題を用意することです。そのために、特定の要件セットを使用したユースケースに焦点を当てます。
私たちのユースケースは、動的な動作を伴うWebアプリのレイアウトで構成されています。ヘッダー、フッター、ナビゲーションメニュー、サブナビゲーションなどの固定要素と、スクロール可能なコンテンツセクションがページに表示されます。具体的なレイアウト要件は次のとおりです。
手始めに、クラシックCSSを使用したサンプル実装で使用するHTML5マークアップを次に示します。
z-index
CSS2では、固定配置を使用する配置レイアウトモデルを採用することで、ページ上の固定要素(ヘッダー、フッターなど)を実現できます。
さらに、 z-index
固定要素がページ上の他のコンテンツの「上」にとどまるようにするCSSプロパティ。 z-index
プロパティは、要素のスタック順序を指定します。スタック順序が大きい要素は、常にスタック順序が小さい要素の「上」にあります。 z-index
に注意してくださいプロパティはでのみ機能します 配置 要素。この例では、任意にwidth
を使用します。固定要素が視覚的に最前線にとどまるようにするための値20(デフォルトよりも高い)。
また、 #header, #footer { position: fixed; width: 100%; z-index: 20; } #header { top: 0; height: 5em; } #footer { bottom: 0; height: 3em; }
プロパティを100%に設定します。これは、要素に使用可能なすべてのスペースを水平方向に使用するようにブラウザに指示します。
#nav
OK、これがヘッダーとフッターです。しかし、#subnav
はどうですかおよび#nav
?
#subnav
の場合およびtop
、として知られているもう少し洗練された手法を使用します CSS拡張 、要素を次のように配置するときに使用できます 修繕 (つまり、ページ上の固定位置)または 絶対の (つまり、最も近い位置を基準にして指定された位置に 配置 祖先または包含ブロックへ)。
垂直方向の拡張は、両方を設定することによって達成されます bottom
そして left
要素のプロパティを固定値に設定するため、要素は垂直方向に拡張され、それに応じて残りの垂直方向のスペースが使用されます。基本的に、要素の上部をページの上部から特定の距離に結び付け、要素の下部をページの下部から特定の距離に結び付けることで、要素が拡張されて垂直方向のスペース全体が埋められます。それらの2つのポイントの間。
同様に、水平方向の拡張は、両方を設定することによって達成されます right
そして #nav, #subnav { position: fixed; top: 6em; /* leave 1em margin below header */ bottom: 4em; /* leave 1em margin above footer */ z-index: 20; } #nav { left: 0; width: 5em; } #subnav { left: 6em; /* leave 1em margin to right of nav */ width: 13em; }
要素のプロパティを固定値に設定するため、要素は水平方向に拡張され、それに応じて残りの水平方向のスペースが使用されます。
このユースケースでは、垂直展開を使用する必要があります。
margin
メインのスクロール可能なコンテンツ領域は、デフォルトの(静的な)配置に依存するだけで、要素はドキュメントフローに表示される順序でレンダリングされます。このページの他のすべては固定位置にあるため、ドキュメントフローに含まれるのはこの要素だけです。その結果、適切に配置するために必要なのは、 #main { margin: 6em 0 4em 20em; }
固定ヘッダー、フッター、およびnav / subnavとの重複を回避するためのプロパティ:
5em
これで、CSS2を使用してユースケースの基本的なレイアウト要件を満たしましたが、動的機能の追加要件を満たす必要があります。
要件では、ナビゲーションメニューにはデフォルトでアイコンのみが表示されますが、テキストを表示するように展開することもできます(その後、折りたたんでアイコンのみを表示することもできます)。
#nav { left: 0; width: 5em; &.expanded { /* Sass notation */ width: 10em; } }
を追加することから始めましょう展開したときのナビゲーションメニューの幅に合わせます。これを行うには、ナビゲーションメニュー要素に動的に追加または削除できる「拡張」CSSクラスを作成します。
$('.layout-classic #nav').on('click', 'li.nav-toggle', function() { $('#nav’').toggleClass('expanded'); });
次に、ユーザーがナビゲーショントグルアイコンをクリックしたことに基づいて、ナビゲーションメニューを展開モードと折りたたみモードの間で動的に切り替えるために使用できるJavaScriptコードの例(この例ではjQueryを使用)を示します。
#subnav { left: 6em; width: 13em; &.expanded { left: 11em; /* move it on over */ } } #main { margin: 6em 0 4em 20; z-index: 10; &.expanded { margin-left: 25em; /* move it on over */ } }
これにより、ナビゲーションメニューを動的に展開または折りたたむことができるようになりました。すごい。
まあ、ちょっと素晴らしいですが、完全ではありません。 ナビゲーションメニューは拡大および縮小できるようになりましたが、ページの他の部分とうまく連携しません。展開されたナビゲーションメニューがサブナビゲーションとオーバーラップするようになりましたが、これは間違いなく望ましい動作ではありません。
これにより、CSS2の重要な制限の1つが明らかになります。つまり、 仕方 固定位置の値でハードコーディングする必要があるのは多すぎます。 その結果、展開されたナビゲーションメニューに対応するために再配置する必要があるページ上の他の要素について、次のように定義する必要があります。 追加 「拡張された」CSSクラス さらにもっと 固定位置の値。
$('.layout-classic #nav').on('click', 'li.nav-toggle', function() { $('#nav, #subnav, #main').toggleClass('expanded'); });
次に、JavaScriptコードを拡張して、ユーザーがナビゲーショントグルをクリックしたときに、これらの他の要素の動的調整も追加する必要があります。
display: none
OK、それはうまくいきます。
次に、サブナビゲーションメニューを非表示にするページをいくつか用意するという要件に対処しましょう。具体的には、ユーザーがメインナビゲーション領域の「ユーザー」アイコンをクリックしたときにサブナビゲーションメニューを非表示にする必要があります。
したがって、最初に、.hidden { display: none; }
を適用する新しいクラス「hidden」を作成します。
#subnav
また、JavaScript(jQuery)を使用して、「非表示」のCSSクラスを$('#nav.fa-user').on('click', function() { $('#subnav').toggleClass('hidden'); });
に適用します。ユーザーがユーザーアイコンをクリックしたときの要素:
#subnav
この追加により、#subnav
ユーザーが「ユーザー」アイコンをクリックすると、要素が適切に非表示になります。 しかし、それが占めていたスペースは未使用のままです 、#subnav
によって空いたスペースを使用するために拡張する他の要素ではなく素子。
グーグルマテリアルデザインの使い方
main
を非表示にしたときに目的の動作を取得するため要素として、あまり知られていないが非常に便利なCSSセレクターの1つを採用します。 隣接する兄弟セレクター 。
ザ・ 隣接する兄弟セレクター 指定した最初の要素の直後に続く2番目の要素のインスタンスのみを選択して、2つの要素を指定できます。
たとえば、以下では、IDがsubnav
の要素のみを選択します。それ すぐに IDが#subnav + #main { margin-left: 20em; }
の要素をフォローします。
#main
上記のCSSスニペットは、20em
の左マージンを設定します〜#subnav
場合に限り 表示された#nav
の直後に続きます。
ただし、expanded
の場合展開されます(これにより、以前のコードに基づいて、#main
クラスも#main
に追加されます)、#subnav + #main.expanded { margin-left: 25em; }
の左マージンを移動します。 25emまで。
#subnav
そして、#main
の場合が非表示の場合、#nav
の左マージンを移動します#subnav.hidden + #main { margin-left: 6em; }
のすぐ隣にある6emまでずっと:
#subnav
(注:隣接する兄弟セレクターを使用することの1つの欠点は、表示されているかどうかに関係なく、常に#subnav
がDOMに存在することを強制することです。)
最後に、#nav
の場合非表示で#main
が展開されたら、11em
の左マージンを設定します#subnav.hidden + #main.expanded { margin-left: 11em; }
で:
calc()
これにより、重いJavaScriptコードなしで物事を結び付けることができますが、ページに要素を追加すると、このコードがどれほど複雑になるかを確認することもできます。 CSS2を使用すると、 たくさん 物事を適切に機能させるには、位置値のハードコーディングが必要です。
CSS3は、大幅に強化された機能とレイアウト手法を提供し、ハードコードされた値への依存を大幅に減らし、使いやすくします。 CSS3は本質的に、より動的な動作をサポートするように設計されており、その意味で、より「プログラム可能」です。これらの新機能のいくつかを、ユースケースに関連して調べてみましょう。
calc()
関数新しい CSS3 calc()
関数 CSSプロパティ値を動的に計算するために使用できます(ただし、 サポートは異なります ブラウザ間で)。 +
に提供される式関数は、標準の演算子優先規則を使用して、基本的な算術演算子(-
、*
、/
、calc()
)を組み合わせた任意の単純な式にすることができます。
#nav, #subnav { position: fixed; height: calc(100% - 10em); /* replaces */ z-index: 20; }
の使用関数は、CSS2で必要な値のハードコーディングの多くを回避するのに役立ちます。私たちの場合、これにより、CSS拡張をより動的に実現できます。例えば:
height
上記でcalc()
top:6em
を使用した仕様関数を使用すると、CSS2でbottom:4em
を使用した場合と同じ結果が得られます。およびtop
ですが、はるかに柔軟で適応性のある方法で、ハードコーディングする必要はありませんbottom
およびdisplay
位置の値。
Flexbox CSS3で導入された新しいレイアウトです( サポートはブラウザによって異なります )。フレックスボックスレイアウトを使用すると、さまざまな画面サイズ、解像度、およびデバイス間で予測どおりに動作するように、ページ上の要素を簡単に配置できます。したがって、これは次のコンテキストで特に役立ちます。 レスポンシブウェブデザイン 。
主な機能は次のとおりです。
Flexboxは、独自の用語と概念のセットを導入しています。これらのいくつかは次のとおりです。
flex
を持つ要素プロパティをinline-flex
に設定またはflex-directio
これは、フレックスアイテムのコンテナ要素として機能します。flex-wrap
n それは 主軸 フレックスアイテムが配置されます。ザ・ 交差軸 その場合、は主軸に垂直な軸です。main size
プロパティ。cross size
です。および.layout-flexbox { display: flex; flex-direction: column; }
は、それぞれフレックスコンテナの主軸と交差軸のサイズを指定します。さて、その簡単な紹介で、フレックスボックスレイアウトを使用している場合に使用できる代替マークアップを次に示します。
content-area
このユースケースの例では、メインレイアウト(ヘッダー、コンテンツ、フッター)が垂直であるため、列レイアウトを使用するようにフレックスボックスを設定します。
#nav
メインレイアウトは垂直ですが、コンテンツ領域の要素(nav、subnav、main)は水平にレイアウトされています。 各フレックスコンテナは一方向のみを定義できます(つまり、そのレイアウトは水平または垂直のいずれかである必要があります)。したがって、レイアウトでこれ以上のことが必要な場合(アプリのレイアウトの場合は一般的です)、それぞれが異なる方向のレイアウトを持つ複数のコンテナーを相互にネストできます。
そのため、#subnav
、#main
、およびflex
をラップするコンテナ(私はflex: ;
と呼んでいます)を追加しました。このようにして、全体的なレイアウトを垂直に、コンテンツ領域のコンテンツを水平にレイアウトすることができます。
フレックスアイテムを配置するために、プロパティflex-grow
を使用します。これはflex-shrink
の省略形です。これらの3つのフレックスプロパティは、次のように、フレックスアイテムの間に残っている空きスペースをフロー方向にどのように分配するかを決定するプロパティです。
設定#header { flex: 0 0 5em; } #footer { flex: 0 0 3em; }
およびflex-grow
両方がゼロの場合、アイテムのサイズは 修繕 また、使用可能な空き領域が多かれ少なかれあることに対応するために、拡大または縮小することはありません。サイズが固定されているため、ヘッダーとフッターに対してこれを行います。
flex-shrink
アイテムに使用可能なすべての空き領域を使用させるには、そのflex-basis
を設定しますおよびauto
両方の値を1に設定し、そのcontent-area
を設定しますdisplay: flex
の値。これは、コンテンツ領域が使用可能なすべての空き領域を占有するようにするために行うことです。
そして、前に述べたように、flex-direction: row;
内のアイテムが必要です行方向にレイアウトするため、#nav
を追加します。および#subnav
。これにより、content-areaはcontent-area
、.content-area { display: flex; flex-direction: row; flex: 1 1 auto; /* take up all available space */ margin: 1em 0; min-height: 0; /* fixes FF issue with minimum height */ }
の新しいフレックスコンテナになります。および `#main。
これが、#nav
のCSSの最終的な結果です。
#subnav
コンテンツ領域では、両方のflex
および#nav { flex: 0 0 5em; margin-right: 1em; overflow-y: auto; } #subnav { flex: 0 0 13em; overflow-y: auto; margin-right: 1em; }
サイズが固定されているので、overflow-y: hidden
を設定するだけです。それに応じてプロパティ:
#main
(コンテナの高さを超えてオーバーフローするコンテンツを克服するために、これらのCSS仕様に#main { flex: 1 1 auto; overflow-y: auto; }
を追加したことに注意してください。Chromeは実際にはこれを必要としませんが、FireFoxは必要です。)
layout-flexbox
残りの空き領域を占有します。
layout-classic
これはすべて良さそうなので、動的な動作をこれに追加して、それがどのように行われるかを見てみましょう。
JavaScriptは以前のものと同じです(ここを除いて、指定するCSS要素コンテナークラスは$('.layout-flexbox #nav’).on('click', 'li.nav-toggle', function() { $('#nav').toggleClass('expanded'); });
ですが、以前はexpanded
でした):
#nav { flex: 0 0 5em; /* collapsed size */ margin-right: 1em; overflow-y: auto; &.expanded { flex: 0 0 10em; /* expanded size */ } }
display
を追加します次のようにCSSへのクラス:
fr
そして出来上がり!
フレックスボックスレイアウトがすべてを処理するため、今回は幅の変更について他のアイテムに通知する必要がないことに注意してください。
残っているのは、サブナビゲーションを非表示にすることだけです。そして、何を推測しますか?これも、以前と同じJavaScriptコードを使用して、追加の変更なしで「正しく機能」します。 Flexboxは空き領域を認識しており、追加のコードなしでレイアウトを自動的に機能させます。かなりクール。
Flexboxは、垂直要素と水平要素の両方を中央に配置するいくつかの興味深い方法も提供します。ここで、プレゼンテーション言語に空き領域の概念を含めることがいかに重要であるか、およびこれらの種類の手法を使用してコードをスケーラブルにすることができるかを理解します。一方、ここでの概念と表記法は、従来のCSSよりも習得するのに少し時間がかかる場合があります。
FlexboxレイアウトがCSS3の最先端にある場合、グリッドレイアウトは最先端にあると言えます。 W3C仕様はまだドラフト状態であり、まだ かなり限定されたブラウザサポート 。 (Chromeでは、の「実験的なWebプラットフォーム機能」フラグを使用して有効になります chrome:// flags )。
とはいえ、私は個人的にこのドラフトを革命的なものとは考えていません。むしろ、 HTML5の設計原則 状態: 「慣行がすでに著者の間で広まっている場合は、それを禁止したり、何か新しいものを発明したりするのではなく、それを採用することを検討してください。」
したがって、マークアップベースのグリッドは長い間使用されてきたため、CSSグリッドレイアウトは実際には同じパラダイムに従っており、マークアップ要件のないプレゼンテーション層ですべての利点とはるかに多くの利点を提供します。
一般的な考え方は、要素を配置できる定義済み、固定、または柔軟なグリッドレイアウトを用意することです。フレックスボックスと同様に、フリースペースの原則にも基づいて機能し、同じ要素で垂直方向と水平方向の両方の「方向」を定義できるため、コードサイズと柔軟性に利点があります。
python-telegram-bot
グリッドレイアウトでは、2種類のグリッドが導入されています。つまり、 明示的 そして 暗黙 。簡単にするために、ここでは明示的なグリッドに焦点を当てます。
フレックスボックスと同様に、グリッドレイアウトには独自の用語と概念のセットが導入されています。これらのいくつかは次のとおりです。
.layout-grid { display: grid; grid-template-columns: auto 0 auto 1em 1fr; grid-template-rows: 5em 1em 1fr 1em 3em; }
を持つ要素プロパティを「grid」または「inline-grid」に設定します。このプロパティには、事前定義されたグリッドに配置および位置合わせすることにより、含まれる要素が配置されます(明示モード)。グリッドは、グリッドコンテナのスペースをグリッドセルに分割する、交差する水平グリッド線と垂直グリッド線のセットです。グリッド線には2つのセットがあります。 1つは列を定義するためのもので、もう1つは行を定義するためのものです。display: grid;
で指定されたディメンション単位。グリッドコンテナの空き領域の一部を表します。
グリッドレイアウトを使用している場合に使用できる代替マークアップは次のとおりです。
grid-template-columns
このレイアウトでは、 ない このタイプのレイアウトでは、同じグリッドコンテナ内で両方向の要素スペースの指定を定義できるため、フレックスボックスの場合と同様に、コンテンツ領域に追加のラッパーが必要です。
今すぐCSSを掘り下げてみましょう。
grid-template-rows
grid-template-columns: auto 0 auto 1em 1fr;
を定義しました私たちのコンテナに。 auto
および#nav
プロパティはそれぞれ、グリッドトラック間のスペースのリストとして指定されます。つまり、これらの値はグリッド線の位置ではありません。むしろ、それらは スペースの量 2つのトラックの間。
測定単位は次のように指定できることに注意してください。
だから#subnav
で私たちは持っているでしょう:
auto
の2列を定義する1トラック幅(#subnav
スペース)1em
のマージンは要素レベルであり、存在する場合と存在しない場合があります。このようにして、ダブルガターが発生しないようにします)1fr
の2列を定義する1トラック幅(#main
スペース)auto
の1つの溝#nav
を使用した1トラック#subnav
の場合(残りのスペースをすべて使用します)ここではgrid-template-rows: 5em 1em 1fr 1em 3em;
を多用しますトラックの値。これにより、行の位置とサイズが最大コンテンツによって定義される動的な列を作成できます。 (したがって、#header
要素と#footer
要素のサイズを指定する必要があります。これについては、後ほど説明します。)
同様に、行の行には1em
があります。それは私たちの#header { grid-column: 1 / 6; grid-row: 1 / 2; } #footer { grid-column: 1 / 6; grid-row: 5 / 6; } #main { grid-column: 5 / 6; grid-row: 3 / 4; overflow-y: auto; }
を設定しますおよびgrid-column
grid-row
を使用している間、残りの空き領域を使用するために修正され、その間のすべての要素側溝。
次に、定義したグリッドに配置する実際の要素をどのように配置するかを見てみましょう。
grid-column-start
これは、ヘッダーをグリッドライン1と6(全幅)の間に配置し、行のグリッドライン1と2の間に配置することを指定します。フッターについても同じですが、(最初の2行ではなく)最後の2行の間にあります。そして、メインエリアはそれが占めることになっているスペースに適切に設定されています。
grid-column-end
に注意してくださいおよびgrid-row-start
プロパティは、grid-row-end
を指定するための省略形です。 / #nav
および#subnav
/ #nav
、それぞれ。
では、#subnav
に戻りましょう。および#nav { width: 5em; grid-column: 1 / 2; grid-row: 3 / 4; &.expanded { width: 10em; } } #subnav { grid-column: 3 / 4; grid-row: 3 / 4; width: 13em; /* track has gutter of 0, so add margin here */ margin-left: 1em; }
。以前に配置したので#nav
および#subnav
自動値を使用してトラックに追加するには、これらの要素の幅を指定する必要があります(拡張モードでも同じです。幅を変更するだけで、残りはグリッドレイアウトが処理します)。
これで、
|_+_|を切り替えることができますまた、
|_+_|を非表示/削除しますそして、すべてが完璧に機能します!グリッドレイアウトでは、線にエイリアスを使用することもできます。そのため、グリッドを変更しても、グリッド線ではなく名前にマップされるため、コードが分割されることはありません。これがより多くのブラウザによってより広くサポートされることを間違いなく楽しみにしています。
従来のCSS手法を使用しても、多くのWeb開発者が認識または利用するよりもはるかに多くのことを達成できます。とは言うものの、これの多くは非常に面倒であり、スタイルシート全体で値を繰り返しハードコーディングする必要があります。
CSS3は、プログラミングが非常に簡単で、以前のCSS仕様の面倒な作業の多くを回避する、はるかに洗練された柔軟なレイアウト手法の提供を開始しました。
CSS2とCSS3の両方でこれらの手法とパラダイムを習得することは、ユーザーエクスペリエンスとコードの品質の両方を最適化するためにCSSが提供するすべてを活用するために不可欠です。この記事は、CSSのパワーと柔軟性で達成できるすべてのことを学ぶための氷山の一角を表しています。どうぞ!
関連: * SMACSSの探索:CSSのスケーラブルでモジュラーなアーキテクチャ*