いくつかのピクセルの「ステップ」で要素の幅を変更する

残念ながら、ここでは純粋なCSSを実行できないことを事前に予約します。FirefoxとIE8 +は、ブロックの幅を計算するために正確すぎます(はい、この場合は悪い)。 ただし、これらのブラウザでは、理想を達成する必要がある場合は、簡単なスクリプトが数行追加されますが、これはすべての魅力を台無しにします。



すべてを読むのが面倒な人のために、最終バージョンへのリンク: jsfiddle.net/XeFTr/11



ポイントは何ですか?



一番下の行は、ページ上にいくつかの子要素を持つゴムブロックを表示することが必要な場合があり、子は完全に表示されるか、まったく表示されない必要があるということです。 最も単純な例は、スクロールと矢印が両側にあるいくつかの写真のリボンです。 側面からトリミングされた画像は、「オーバーフロー:隠された」の下から見ると非常にいように見えます。 解決策は、ラッパーの幅を常にピクセル数の倍数にすることです。

もちろん、子孫の幅が要素ごとに異なる場合、このメソッドは意味がありません。



どのように機能しますか?



操作の原則は、親の幅に基づいてパーセンテージで指定されている場合、ほとんどのブラウザが子の幅を計算することです。 したがって、要素の幅が1000%の場合、親の幅がピクセルごとに変化すると、要素自体が10ピクセルずつ伸縮します。 実際には、それだけです。



このことは、IE6の「ジャンプ」ブロックに関するバグを修正するという文脈で、2008年にSergei Chikuyonokが行ったLebedevスクリーンキャストで説明されています。 しかし、驚いたことに、この楽しいテクノロジーの説明がHabréで見つかりませんでした。



これを書く方法は?



真空中の球体要素を考えます。最初は「オーバーフロー:隠された」ブロックと、全体の幅がラッパーの幅を超える一連の子孫を持つ非常に幅の広い要素のみで構成されます。



<div class="wrapper"> <ul class="itemList"> <li class="item"></li> <li class="item"></li> <li class="item"></li> <li class="item"></li> <li class="item"></li> <li class="item"></li> </ul> </div>
      
      





 .wrapper { border: 1px solid black; margin: 10px; overflow: hidden; width: 60%; /*        */ } .itemList { height: 90px; list-style: none; margin: 0; padding: 0; width: 10000%; /*        */ } .item { background: green; /*   ,    */ display: inline; /*  ,    IE6 */ float: left; height: 80px; margin: 5px; padding: 0; width: 140px; }
      
      





ライブ例: jsfiddle.net/KKSCe/4



したがって、要素のリストがあり、それぞれの幅(マージンを含む)は150pxです。 当然、リストの最後の要素は150のうち1つのケースで完全に表示されます。11の場合:5ピクセルの右マージンを表示しないようにし、左マージンが前の要素の一部であることを受け入れます。 :-)



上記の説明から、「。wrapper」ブロックにラッパーを追加し、「。wrapper」自体をこのラッパーの幅の150倍に設定する必要があることは明らかです。 また、追加の操作を行わずに「幅:15000%」と記述した場合、結果が意図したものとは多少異なることも明らかです。 「.wrapper」は、画面幅の60%の幅を維持する必要があります。 これは、比率によって計算されるラッパーの幅が小さいことで補正されます。

15000/100 = 60 / x

x = 0.4

このように書きます:



 <div class="pre-wrapper"> <div class="wrapper">......</div> </div>
      
      





 .pre-wrapper { margin: 10px; width: 0.4%; } .wrapper { border: 1px solid black; overflow: hidden; width: 15000%; }
      
      





ライブの例(Chromeなどで確認): jsfiddle.net/XeFTr/9

そこに表示領域を広げて、すべてがクールに機能することを確認できます。 ブロックは、150pxの倍数の幅を受け入れます。

それは素晴らしいようです!



しかし、それはそれほど滑らかではありません



問題は、この例のように、場合によってはラッパーの幅を1パーセント未満に設定する必要があることです(ステップを100ピクセルより大きくする必要がある場合)。 ほとんどのブラウザはそれを飲み込んで、すべてを正しく考えます。 IE6でも。 しかし、最新バージョンを含むOperaでは、これは大惨事です。 Operaは1%未満の値を理解しません。



ソリューションは非常に簡単ですが、より多くのHTMLが必要です。 0.4%の幅で1つのブロックを作成する代わりに、2つを実行します。 最初の幅は1%で、2番目の幅は最初の入れ子に40%です。 ここで、Operaは子音になります。



 <div class="pre-wrapper"> <div class="opera-fix"> <div class="wrapper">......</div> </div> </div>
      
      





 .pre-wrapper { margin: 10px; width: 1%; } .opera-fix { width: 40%; }
      
      





ライブ例: jsfiddle.net/XeFTr/8



1%未満の値を使用することは、他のブラウザーでは少し横向きになる可能性がありますが、私はこれを見ていません。 間違っている場合は修正してください。

ただし、いずれにしても、小数のパーセンテージ値は特に適切ではありません。



そのため、FirefoxとIEの最新バージョンを除き、すべてがどこでも機能します。 それも修正しましょう。



過度に正確なブラウザー用のスクリプト



簡単にするために、jQueryを使用します。 機能とマークアップは、実験室の条件にも使用されます。

 $(function() { if ( $.browser.mozilla || ($.browser.msie && $.browser.version >= 8) ) { resizeFix(); $(window).resize(resizeFix); } }); function resizeFix() { var w, h = $('.wrapper'), i = $('.item').outerWidth() + parseInt($('.item').css('marginLeft')) * 2; h.width(''); w = Math.floor(h.width() / i) * i; h.width(w + 'px'); }
      
      





最終バージョン: jsfiddle.net/XeFTr/11



まとめます



人生に近い例では、あらゆる種類の矢印、フレームなどがあります。 それらの配置(特に、ブロックが引き伸ばされる側からの要素の配置)はまったく同じ方法で行われます。



Firefox、Opera、Chrome、IE6-9、Safari for Windowsのパフォーマンスを確認しました。

MacOS、KonquerorなどのさまざまなSafariですべてを見ることができれば素晴らしいと思います。

また、コメント/修正も歓迎します。



執筆は、上記のスクリーンキャストと、このトピックに関するその後の独立した研究と実験に基づいています。



All Articles