軽量の石積みソリューション
5月に、FirefoxがCSSグリッドに石積みレイアウト機能を追加したことを知りました。石積みのレイアウトは、私がいつもゼロから実装したかったものですが、どこから始めればいいのかわかりません。だから私は自然にデモを見て、この新しいCSS機能がどのように機能するかを理解したとき、インスピレーションの閃光がありました。
現在、サポートはFirefoxに限定されています(そして、特定のフラグが有効になっている場合のみ)が、これにより、現在サポートがないブラウザをカバーできるJavaScriptの実装の出発点が得られます。
Firefoxはgrid-template-rows
(例に示す)またはgrid-template-columns
masonry
値に設定することにより、CSSの石積みレイアウトを実装します。
私のアプローチは、この機能を活用してブラウザをサポートし(繰り返しますが、今のところFirefoxのみを指します)、ブラウザの残りのためにJavaScriptフォールバックスキームを作成することです。画像グリッドの特定のケースを使用してこれを達成する方法を見てみましょう。
まず、フラグを有効にします
これを行うには、Firefoxのabout:config
と「Masonry」を検索します。これによりlayout.css.grid-template-masonry-value.enabled
フラグが表示されます。これは、 false
(デフォルト値)からtrue
にダブルクリックすることで有効にできます。
いくつかのマークアップから始めましょう
HTML構造は次のとおりです。
<img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174364597525146.jpg" class="lazy" alt="軽量の石積みソリューション">
それでは、いくつかのスタイルを適用しましょう
まず、最上位要素をCSSグリッドコンテナとして設定します。次に、画像の最大幅、たとえば10em
を定義します。また、これらの画像がグリッドコンテンツボックスで利用可能な任意のスペースに収縮したいと考えています。ビューポートが狭くなりすぎて10em
列グリッドを収容できない場合、実際に設定された値はMin(10em, 100%)
です。レスポンシブデザインは最近では非常に重要であるため、固定数の列を使用する代わりに、この幅の幅をできるだけ多くの列を自動的に適応させます。
$ w:min(10em、100%); .grid - masonry { ディスプレイ:グリッド; Grid-Template-Columns:Repeat(auto-fit、$ w); > * {width:$ w; } }
SASSの競合を避けるために、min Min()
min()
)を使用したことに注意してください。
わかりました、これはグリッドです!
しかし、それはあまり素晴らしいグリッドではないので、その内容を強制的に水平方向に中心にしてから、間隔値( $s
)に等しいグリッドギャップと塗りつぶしを追加しましょう。また、視聴を容易にするための背景を設定します。
$ s:.5em; /*石積みグリッドスタイル*/ .grid - masonry { /*以前のスタイルと同じ*/ justify-content:center; グリッドギャップ:$ s; パディング:$ s; } /*美化スタイル*/ html {背景:#555; }
グリッドを少し美化した後、グリッドプロジェクト(つまり、画像)についても同じことをすることになりました。フィルターを適用して、少し丸い角と影のある追加のスタイルを追加しながら、もう少し均一に見せてみましょう。
img { ボーダーラジウス:4px; Box-Shadow:2PX 2PX 5PX RGBA(#000、.7); フィルター:セピア(1); }
ここで、石積みのレイアウトをサポートするブラウザの場合、それを宣言する必要があります。
.grid - masonry { /*以前のスタイルと同じ*/ グリッドテンプレート列:巨大な; }
これはほとんどのブラウザでは機能しませんが、FirefoxではFirefoxで説明されています。
しかし、他のブラウザはどうですか?これが私たちが必要とするものです...
JavaScriptフォールバックソリューション
ブラウザが実行する必要があるJavaScriptコードを保存するために、最初に.grid--masonry
要素があるかどうか、およびブラウザがgrid-template-rows
のmasonry
値を理解および適用したかどうかを確認します。これは一般的なアプローチであることに注意してください。これは、ページにそのようなメッシュが複数ある可能性があると仮定しています。
let grids = [... document.queryselectorall('。grid - masonry ')]; if(grids.length && getComputedStyle(grids [0])。gridtemplaterows!== 'masonry'){ console.log( 'oops、masonryレイアウトはサポートしませんか?'); } それ以外 { console.log( '良すぎる、操作は不要!'); }
新しい石積み機能がサポートされていない場合、各石積みメッシュの行ギャップとメッシュアイテムが取得され、列の数を設定します(各メッシュは最初は0です)。
let grids = [... document.queryselectorall('。grid - masonry ')]; if(grids.length && getComputedStyle(grids [0])。gridtemplaterows!== 'masonry'){ grids = grids.map(grid =>({ _el:グリッド、 ギャップ:parsefloat(getComputedStyle(grid).gridrowgap)、 アイテム:[... grid.childnodes] .filter(c => c.nodetype === 1)、 NCOL:0 })); grids.foreach(grid => console.log( `grid item:$ {grid.items.length}; grid gap:$ {grid.gap} px`)); }
子ノードが要素ノードであることを確認する必要があることに注意してください(これは、 nodeType
が1であることを意味します)。それ以外の場合は、プロジェクトアレイ内のキャリッジリターンで構成されるテキストノードになってしまう可能性があります。
進む前に、ページがロードされ、要素がまだ動いていることを確認する必要があります。この問題に対処したら、各グリッドを取り、現在の列数を読み取ります。これがすでに持っている値と異なる場合は、古い値を更新し、グリッドアイテムを再配置します。
if(grids.length && getComputedStyle(grids [0])。gridtemplaterows!== 'masonry'){ grids = grids.map(/*は以前と同じ*/); function layout(){ grids.foreach(grid => { /*サイズ/ロードされた列番号を取得*/ let ncol = getComputedStyle(grid._el).gridtemplatecolumns.split( '').length; if(grid.ncol!== ncol){ grid.ncol = ncol; console.log( 'グリッドアイテムの再配置'); } }); } addeventListener( 'load'、e => { レイアウト(); /*初期負荷*/ addeventListener( 'resize'、layout、false); }、 間違い); }
layout()
関数を呼び出すことは、初期負荷とサイズ変更の両方の場合に実行する必要がある操作であることに注意してください。
グリッドアイテムを再配置するための最初のステップは、すべてのアイテムから上限を削除することです(これは、現在のサイズ変更前に石積み効果を達成するために非ゼロ値に設定できます)。
ビューポートが十分に狭く、列が1つしかない場合は、完了です!
それ以外の場合は、最初のncol
アイテムをスキップして、残りをループします。考慮された各アイテムについて、上記のアイテムのボトムエッジ位置と上端の現在の位置を計算します。これにより、上端が上記のプロジェクトの下端の下のグリッドギャップにあるように、必要な垂直方向の動きの量を計算できます。
/*列の数が変更された場合*/ if(grid.ncol!== ncol){ /*更新された列の数*/ grid.ncol = ncol; /*初期位置決めを復元する、境界線なし*/ grid.items.foreach(c => c.style.RemoveProperty( 'marve-top')); /*複数の列がある場合*/ if(grid.ncol> 1){ grid.items.slice(ncol).foreach((c、i)=> { prev_fin = grid.items [i] .getBoundingClientRect()。下、 /*上記のプロジェクトのボトムエッジ* / curr_ini = c.getBoundingClientRect()。top; /*現在のプロジェクトの最上端*/ c.style.margintop = `$ {prev_fin grid.gap -curr_ini} px`; }); } }
これで、作業クロスブラウザーソリューションがあります!
いくつかの小さな改善
より現実的な構造
現実の世界では、各画像をフルサイズの画像にリンクに巻き付ける可能性が高く、大きな画像をライトボックスに開くことができます(または、フォールバックとしてナビゲートします)。
<a href="https://www.php.cn/link/849c1f472f609bb4a3bacafef177f541"> <img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174364597550777.jpg" class="lazy" alt="軽量の石積みソリューション"> </a>
これは、CSSを少し変更する必要があることを意味します。グリッドアイテムの幅を明示的に設定する必要はなくなりましたが、リンクがリンクになっているため、 align-self: start
必要があります。画像とは異なり、デフォルトでは行の高さ全体をカバーし、アルゴリズムを乱すためです。
.grid - masonry> * {align-self:start; } img { 表示:ブロック; /*下部の奇妙な余分なスペースを避けます*/ 幅:100%; /*以前のスタイルと同じ*/ }
最初の要素をメッシュに及ぼします
また、最初のプロジェクトをメッシュ全体に水平に及ぼすこともできます(つまり、おそらくその高さを制限し、画像がオーバーフローまたは変形しないようにする必要があります):
.grid - masonry>:first-child { グリッドコラム:1 / -1; Max-Height:29VH; } img { max-height:継承; オブジェクトフィット:カバー; /*以前のスタイルと同じ*/ }
また、グリッドアイテムのリストを取得して、この伸縮したアイテムを除外するときに、別のフィルターを追加する必要があります。
grids = grids.map(grid =>({ _el:グリッド、 ギャップ:parsefloat(getComputedStyle(grid).gridrowgap)、 アイテム:[... grid.childnodes] .filter(c => c.nodeType === 1 && getComputedStyle(c).gridcolumnend!== -1 )、、 NCOL:0 }));
さまざまなアスペクト比のグリッドアイテムを処理します
ブログなどの目的にこのソリューションを使用したいとします。まったく同じJSとほぼ同一の石積み固有のCSSを保持します。列の最大幅を変更し、最初のアイテムのmax-height
制限を削除するだけです。
以下のデモからわかるように、この場合はソリューションが完全に機能し、ブログ投稿グリッドがあります。
ビューポートのサイズを変更して、この場合にどのように機能するかを確認することもできます。
ただし、たとえば、列の幅をある程度の柔軟性にしたい場合は、
$ w:minmax(min(20em、100%)、1fr);
その後、サイズを変更する際に問題が発生します。
グリッドアイテムの幅の変更と、各アイテムのテキストコンテンツが異なるという事実の組み合わせは、特定のしきい値を超えた場合、グリッドアイテムのテキスト行の数が異なる場合(したがって高さを変更する)ことを意味しますが、他のアイテムはそうではありません。列の数が変更されていない場合、垂直オフセットは再計算されず、オーバーラップまたは大きなギャップになります。
この問題を解決するには、少なくとも1つのアイテムの現在のグリッドの高さが変更されたときにオフセットを再計算する必要があります。つまり、現在のグリッドにゼロ以上のアイテムが高さを変えたかどうかをテストする必要があります。次に、 if
ブロックの最後にこの値をリセットする必要があります。そうすれば、次回アイテムを不必要に再配置する必要がないようにする必要があります。
if(grid.ncol!== ncol || grid.mod){ /*以前と同じ*/ grid.mod = 0; }
わかりましたが、このgrid.mod
値をどのように変更しますか?私の最初のアイデアは、 ResizeObserver
使用することです。
if(grids.length && getComputedStyle(grids [0])。gridtemplaterows!== 'masonry'){ let o = new resizeObserver(entries => { entries.foreach(entry => { grids.find(grid => grid._el === entry.target.parentelement).mod = 1; }); }); /*以前と同じ*/ addeventListener( 'load'、e => { /*以前と同じ*/ grids.foreach(grid => {grid.items.foreach(c => o.observe(c));}); }、 間違い); }
これにより、グリッド列の数が変更されていない場合でも、必要に応じてグリッドアイテムを再配置できます。しかし、条件が利用できないif
でも、それは無意味になります!
これは、少なくとも1つのアイテムの高さまたは幅が変更されたときにgrid.mod
が1に変更されるためです。プロジェクトの高さは、幅の変化によって引き起こされるテキストリフローのために変化します。ただし、ビューポートサイズを調整するたびに幅の変化が発生し、必ずしも高さの変化をトリガーするわけではありません。
そのため、以前のプロジェクトの高さを保存し、 grid.mod
0に残っているかどうかを判断するために変更されたときに変更されたかどうかを確認することにしました。
function layout(){ grids.foreach(grid => { grid.items.foreach(c => { new_h = c.getBoundingClientRect()。height; if(new_h!== c.dataset.h){ c.dataset.h = new_h; grid.mod; } }); /*以前と同じ*/ }); }
それでおしまい!今、私たちは素敵な軽量ソリューションを持っています。圧縮されたJavaScriptは800バイト未満ですが、厳密な石積み関連のスタイルは300バイト未満です。
しかし、しかし、しかし...
ブラウザのサポートはどうですか?
さて、 @supports
、ここで使用されている新しいCSS機能よりも優れたブラウザのサポートを持っているため、良いものを入れて、サポートされていないブラウザに基本的な非整形メッシュを提供できます。このバージョンは、IE9と後方互換性があります。
見た目が違うかもしれませんが、見た目が良く、完璧な機能を備えています。ブラウザをサポートすることは、すべての視覚効果をコピーすることを意味しません。これは、ページが機能し、損傷したりugいたりしないように見えることを意味します。
JavaScriptのない状況はどうですか?
まあ、ルート要素にJavaScriptを介して追加したjs
クラスがある場合にのみ、派手なスタイルを適用できます!それ以外の場合は、すべてのアイテムに対して同じサイズのベースグリッドを取得します。
以上が軽量の石積みソリューションの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









最近GraphQLの作業を開始した場合、またはその長所と短所をレビューした場合、「GraphQLがキャッシュをサポートしていない」または

最近のビットコインの価格が20k $ $ USDを超えており、最近30Kを破ったので、イーサリアムを作成するために深く掘り下げる価値があると思いました

開発者としての段階に関係なく、私たちが完了したタスクは、大小を問わず、個人的および専門的な成長に大きな影響を与えます。

それは&#039; Vueチームにそれを成し遂げてくれておめでとうございます。それは大規模な努力であり、長い時間がかかったことを知っています。すべての新しいドキュメントも同様です。

私はこの非常に正当な質問で誰かに書いてもらいました。 Leaは、ブラウザから有効なCSSプロパティ自体を取得する方法についてブログを書いています。それはこのようなものです。

これらのデスクトップアプリがいくつかあり、目標があなたのサイトをさまざまな次元ですべて同時に表示しています。たとえば、書くことができます

先日、Corey Ginnivanのウェブサイトから、この特に素敵なビットを見つけました。そこでは、スクロール中にカードのコレクションが互いに積み重ねられていました。
