web-dev-qa-db-ja.com

CSS流体列、固定マージン。聖杯の聖杯

更新と概要

賞金が付いた今、この質問をより明確にする義務があると感じています。

また、calc() CSS3ユニットの値がサポートされ、width: calc(25% - 5px)のようなことをするとき、これは子供の遊びになると確信しています。その時点までの心

設計要件を共有するいくつかのプロジェクトのCSSフレームワークに取り組んでいます。つまり、流動的な12列のレイアウトです。 .columnのパーセント幅の浮動(100% / 12) x col_size要素を使用すると、これはかなり簡単です。ただし、列間に固定マージン(または任意の間隔)を追加すると問題が発生します。

私の最初の試みは、説明されているように、それぞれにネストされた.panel子を持つ流体列を使用しました。 HTML/CSSスニペットが続きます(簡潔にするために縮小):

.column{
    float: left;
    display: inline-block;
}

.width-01{ width:  8.3333%; }
.width-02{ width: 16.6666%; }
.width-03{ width:      25%; }
/* etc */

.panel{
    width: 100%;
    padding: 5px;
    box-sizing: border-box; /* so padding doesn't increase width */
}
<div class="column width-02">
    <div class="panel">Width-02</div>
</div>
<div class="column width-03">
    <div class="panel">Width-03</div>
</div>
<div class="column width-02">
    <div class="panel">Width-02</div>
</div>
<div class="column width-05">
    <div class="panel">Width-05</div>
</div>

このスニペットは、下の画像のレイアウトと同様のレイアウトを生成しますが、すべての.panel要素にはすべての側面に5pxパディングがあります。 外側の列のコンテンツエッジをビューポートのエッジと同じ高さにしようとしています(またはその問題の親コンテナ。別のアプローチは、.panelクラスを完全に削除し、列を使用することです。

.column{
    float: left;
    display: inline-block;
    padding-left: 10px;
    box-sizing: border-box;
}

.column:first-child{ padding-left: 0px; }

.width-01{ width:  8.3333%; }
.width-02{ width: 16.6666%; }
.width-03{ width:      25%; }
/* etc */
<div class="column width-02">Width-02</div>
<div class="column width-03">Width-03</div>
<div class="column width-02">Width-02</div>
<div class="column width-05">Width-05</div>

これもうまく機能し、下の画像の結果にさらに近い結果を生成しますが、(actual)問題は、パディングが幅に食い込んでいるということです幅の分布を台無しにする列。 :first-child列には、兄弟よりもコンテンツ領域の幅が大きい10ピクセル(またはマージンサイズは何でも)があります。

これは無害に見えるかもしれませんが、目立たないかもしれません。ただし、exactできるだけ正確に)要素間の幅分布が必要な場合、または必要になる場合がいくつかあります物事を完全に簡単にします。

そして、パディング、マージン、またはそれらの組み合わせを使用するかどうか;流体カラム、固定マージン、均等分布ガタースペースのソリューションで、 "marginal"(*** haha​​ *)コンテンツエリアを奪わないものはありますか隣接する列から?**


元の質問

検索と試行の結果が単純に不足しているため、これは不可能であると結論付けました。どこでも答えが得られる場合、それはここにあると確信しています。

純粋なCSSを使用して、固定幅のマージンを持つ流動的な幅の列レイアウトを実現する方法はありますか?

重要な注意事項:この図は単なる例であり、実現したい特定のレイアウトではありません。特定のソリューションでは、隣接する列の任意の組み合わせを許可する必要があり、合計幅分布は合計で12以下です。一般的な 960グリッド を参考にしてください。)

super_awesome_layout.css
:12列レイアウトでは、列の幅分布画像はそれぞれ2、3、2、5です。

これまでのところ、パーセンテージを使用してnearlyでこれを達成するグリッドに頼ってきました。問題は、マージンを達成するために、各列に追加の子(私はそれらを.panelと呼ぶ)が必要であるということです:

width: 100%;
box-sizing: border-box;
padding: 10px;

これもまた、nearly、問題ありません。このアプローチの問題は、最初と最後の列に外側の「マージン」(10px)があり、各列間の「マージン」が2倍になることです(2 x 10px

確かに、新しいCSS3 calc()値型を含めることで、これをはるかに簡単に解決できます。次の方向の何か:

.width-12 > .panel{ width: 100%; }
.width-09 > .panel{
    width: calc(75% - 10px);
    margin: ...;
}

Javascriptの修正がいくつかあり、「機能する」ものをハッキングしましたが、探しています。神聖な聖杯が存在することを願っています。

次のソリューション、および@avallが提供したもの(確かに単純化するのに良い選択ですが)は、残念ながら私が探しているものではありません。主な問題は、マージンが列間で均等に分散されないことです。

この動作を確認できる唯一の方法は、.panelパディングを5pxなどに減らすことです。

.column:first-child > .panel {
    padding-left: 0px;
}

.column:last-child > .panel {
    padding-right: 0px;
}

/* not necessary? in any case, haven't tested */
.column:only-child > .panel {
    padding-right: 0px;
    padding-left: 0px;
}

IE8が:last-childさらに言えば:only-child)擬似セレクターを認識できないため、この解決策は受け入れられません。

48
Dan Lugg

ようやくわかりました。過去10年間で何百時間も浪費されていました(とにかく1年前には機能しなかったcssに依存していますが)。問題なく解決しました。およびIE8 +で。

2001:A Space Odyssey Musicを準備してください。私はこの船に着陸しています。

この方法の天才とトリックは、インラインブロック要素を使用し、次にワード間隔を使用して負の右マージンを使用して相殺することにあります。それ自体の負の右マージンは要素をまとめ、100%の幅を設定し、その間に物事を収めることができますが、要素は重複したままにします。親に負のマージンを設定すると、合計幅(ヒットしようとしている魔法の「100%幅」マーク)との相互作用への影響に関して、子マージンが元に戻ります。パディングは、要素のサイズを大きくするだけです多くの場合、この問題に対するju審員のリグ付きソリューションのボックスサイズ設定で使用されますが、それ以外の場合(およびマージン)にパディングを使用する能力が失われ、さらに多くの要件が必要になる可能性があります。ラッパー要素。

単語間隔は、インラインブロックである場合、2つの要素間の水平距離を追加または削除する魔法の「3番目の方法」を提供します。その場合、それらは単一の「単語」としてカウントされ、その間の空白は単一の制御可能な「Word-spacing」プロパティ。このトリックは別として、私はこの100%の結果を得る別の方法を知りません。

固定溝フレックスコラムの問題に対する究極の答えを謙虚に提示します。私はここに自分の解決策を「オメガ操作」と名付けます。任意の混合幅列を処理する機能(丸み付けのために正確にまたはわずかに少ない合計幅の100%を追加)、任意のガターサイズ、事前に定義された幅の列数、自動折り返しで任意の量の行を処理し、したがって、インラインブロック要素を使用するため、インラインブロックに付属する垂直方向の配置オプションが提供されます。また、追加のマークアップは不要であり、コンテナーでの単一のクラス宣言のみが必要です(列幅の定義はカウントしません)。コードはそれ自体を物語っていると思います。以下は、10pxガターとパーセンテージのボーナスヘルパークラスを使用した2〜6列のコード実装です。

編集:興味深い難問。わずかに異なる2つのバージョンを取得できました。 1つはmozillaとie8 +用、もう1つはwebkit用です。ワード間隔のトリックはwebkitでは機能しないようです。他のバージョンがwebkitで機能するのにie8 +/mozillaでは機能しない理由はわかりません。両方を組み合わせることで、すべてをカバーできるようになります。この戦術や、この問題を回避するために非常によく似た方法を統一する方法があると確信しています。

EDIT2:ほとんどそれを手に入れました!魔法の text-align: justifyはWebKitをWord間隔のWebKitとほぼ同じ場所に配置します。右側のピクセルの問題と、側溝の余分なスペースのように、間隔はほんの少しずれているように見えます。しかし、それは使いやすく、以前に使用したものよりも列を保持する方が信頼性が高いようです。カラム数が少なくなることはなく、ブラウザが水平スクロールバーを取得するまで圧縮されます。

編集3:それは完璧に少し近づいた。 font-sizeを0に設定すると、オフになっている間隔に関する残りの問題のほとんどが正規化されます。 IE9を修正して、フォントがサイズ0の場合に折りたたむようにします。

EDIT4:IE他のいくつかの流体幅の投稿からの答えを得た:-ms-text-justify: distribute-all-lines。 IE8-10でテスト済み。

/* The Omega Maneuver */
[class*=cols] { text-align: justify; padding-left: 10px; font-size: 0;
             -ms-text-justify: distribute-all-lines; } 

 [class*=cols]>* { display: inline-block; text-align: left; font-size: 13px;
                Word-spacing: normal; vertical-align: top;
                -webkit-box-sizing: border-box;
                   -moz-box-sizing: border-box;
                        box-sizing: border-box; }

.cols2 { Word-spacing: 20px; padding-right: 20px; }
.cols3 { Word-spacing: 30px; padding-right: 30px; }
.cols4 { Word-spacing: 40px; padding-right: 40px; }
.cols5 { Word-spacing: 50px; padding-right: 50px; }
.cols6 { Word-spacing: 60px; padding-right: 60px; }

  .cols2 > * { margin-right: -10px; }
  .cols3 > * { margin-right: -20px; }
  .cols4 > * { margin-right: -30px; }
  .cols5 > * { margin-right: -40px; }
  .cols6 > * { margin-right: -50px; }

一部のヘルパー:

.⅛, .⅛s >* { width: 12.50%; }
.⅙, .⅙s >* { width: 16.66%; }
.⅕, .⅕s >* { width: 20.00%; }
.¼, .¼s >* { width: 25.00%; }
.⅓, .⅓s >* { width: 33.00%; }
.⅜, .⅜s >* { width: 37.50%; }
.⅖, .⅖s >* { width: 40.00%; }
.½, .½s >* { width: 50.00%; }
.⅗, .⅗s >* { width: 60.00%; }
.⅝, .⅝s >* { width: 62.50%; }
.⅔, .⅔s >* { width: 66.00%; }
.¾, .¾s >* { width: 75.00%; }
.⅘, .⅘s >* { width: 80.00%; }
.⅚, .⅚s >* { width: 83.33%; }
.⅞, .⅞s >* { width: 87.50%; }
.blarg-five-twelfs { width: 41.66%; }

あなたはここで栄光の分野の中で私のマグナムの作品を目の当たりにすることができます: http://jsfiddle.net/xg7nB/15/

<div class="cols4">
    <div class="⅙">This is my magnum opus</div>
    <div class="¼">I finally beat css</div>
    <div class="⅙">⚉ ☺ ☻ ♾ ☢</div>
    <div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>

例として4つの等幅(25%)幅のcolsと10pxのガターを使用した絶対的な最小実装は次のようになります。

.fourEqualCols { Word-spacing: 40px; padding: 0 40px 0 10px;
                 text-align: justify; font-size: 0;
                 -ms-text-justify: distribute-all-lines; }

.fourEqualCols>* { margin-right: -30px; width: 25%;
                   display: inline-block; Word-spacing: normal;
                   text-align: left; font-size: 13px; }


<div class="fourEqualCols ">
  <div>GLORIOUSLY CLEAN MARKUP</div>
  <div>I hate extra markup and excessive class props</div>
  <div>Naked code</div>
  <div>get intimate</div>
</div>

このコードは、基本的に既存のグリッドフレームワークをほとんど置き換えますか? arbitrarilyを任意に設定し、幅100%に達する列のセットを作成できる場合、実際にはほとんどの/すべてのグリッドフレームワークよりも優れています。私たちのようにIE7向けに開発していない場合は、ボックスサイズと組み合わせると、border-boxはパディングとボーダーも問題になりません。

編集:ああ、そうですね、コンテナの側面と同じ高さにしたかったのです。これに問題はありません。サイドガターを追加する必要があったため、値を10だけ変更して、パディングと出来上がりを取り除くことができました。 http://jsfiddle.net/bTty3/

[class^=cols] { text-align: justify; font-size: 0;
             -ms-text-justify: distribute-all-lines; } 

 [class^=cols] >* { display: inline-block; text-align: left; font-size: 13px;
                Word-spacing: normal; vertical-align: top;
                -webkit-box-sizing: border-box;
                   -moz-box-sizing: border-box;
                        box-sizing: border-box; }

.cols2 { Word-spacing: 20px; padding-right: 10px; }
.cols3 { Word-spacing: 30px; padding-right: 20px; }
.cols4 { Word-spacing: 40px; padding-right: 30px; }
.cols5 { Word-spacing: 50px; padding-right: 40px; }
.cols6 { Word-spacing: 60px; padding-right: 50px; }
 .cols2 >* { margin-right: 0 }
 .cols2 >* { margin-right: -10px; }
 .cols3 >* { margin-right: -20px; }
 .cols4 >* { margin-right: -30px; }
 .cols5 >* { margin-right: -40px; }
 .cols6 >* { margin-right: -50px; }

同じhtml

<div class="cols4">
    <div class="⅙">This is my magnum opus</div>
    <div class="¼">I finally beat css</div>
    <div class="⅙">⚉ ☺ ☻ ♾ ☢</div>
    <div class="blarg-five-twelfs">I BEAT IT FOREVER</div>
</div>

I beat CSS here's your proof

64
user748221

この純粋なCSS2ソリューションを試してください:デモフィドル

ベースCSSフィドル 化粧品なし)

html, body {
    padding: 0;
    margin: 0;
}
#wrap {
    padding-right: 30px;
    overflow: hidden;
}
.col {
    float: left;
    margin-left: 40px;
    margin-right: -30px;
}
.col:first-child {
    margin-left: 0;
}
.small {
    width: 16.66%;
}
.medium {
    width: 25%;
}
.large {
    width: 41.66%;
}

HTML:

<div id="wrap">
    <div class="col small"></div>
    <div class="col medium"></div>
    <div class="col small"></div>
    <div class="col large"></div>
</div>

IE7、IE8、IE9、Opera 11.50、Safari 5.0.5、FF 6.0、Chrome 13.0。


更新:

ここで、これを任意の数の列で動作させるには、列カウントを指定する追加のクラスをコンテナに追加する必要があります。

<div class="cols-12 count-04">
    <div class="col width-02"></div>
    <div class="col width-03"></div>
    <div class="col width-02"></div>
    <div class="col width-05"></div>
</div>

この更新されたフィドル を参照して、さまざまな列数を示します。

可能性のあるバグ:

理論的には、このソリューションは、任意のブラウザーウィンドウ幅のすべての可能な最小列幅に対して任意の数の列に対して機能するはずです。しかし、すべてのブラウザが処理できないことが判明しています。1。多数の1列幅の列、または2.小さいブラウザウィンドウ幅。

最小幅が1440ピクセルであるすべてのブラウザー(120ピクセルの12倍(10pxのすべてのマージンが占めるスペース))は、ソリューションをうまく処理することに注意してください。また、2つ以上の列幅列を使用すると、ブラウザーの最小幅の要件は実際に720ピクセル(6 * 120ピクセル)に低下します。この最後のケースはより現実的に聞こえますが、それでも、このブラウザーの動作を説明することはできません。

this fiddle で示されているように、追加のlast columnクラスを導入して問題を修正しようとしましたが、ブラウザー幅が小さい場合の問題は解決しません。ただし、幅のパーセンテージが壊れているために小さな丸め誤差が解決されますが、その問題は無視できると思います。

これに関する他のCSSの専門家から聞きたいので、賞金を追加しました。

8
NGLN

使ってみませんか

.column > .panel {
    padding: 10px 0 10px 10px;
}

.column:first-child > .panel {
    padding-left: 0px;
}

最後の子を使用せずに、ボックス間にのみ10pxのスペースを作成します。

7
avall

元の質問を参照して、「純粋なCSSを使用して、固定幅のマージンで流動的な幅の列レイアウトを実現する方法はありますか?」

この種の質問でCSSが非常に困難になるのは驚くべきことです。先週、境界、マージン、パディングを含む独自の「聖杯」を作成するための「ベーステンプレート」に取り組んでいます...この種の質問ではCSSが失敗するようです。頭に浮かぶ疑問は非常に簡単ですが、CSS、特にクロスブラウザで達成することは(ほぼ?)不可能になります。

面白い部分は、これらの質問がテーブルを使用して簡単に解決されることです。ほとんどの引数が弱い、または偽であるため、「セマンティクス」や「簡単な概要」などの曖昧な引数の代わりにdivを使用するようにウェブ社会に強制されている理由がわかりません。テーブルがより多くの問題を引き起こしていると言っている人々は、CSSにある本当の難しさを明らかに理解していません。

とにかく、テーブルの構造が必要な場合(コラムはテーブルの一部であるため)、「display:table」を使用することをお勧めします。

純粋なCSSを使用して元の質問の下にある画像を作成するには、次を使用できます。

[〜#〜] css [〜#〜]

html,body{
    margin: 0px; 
    padding: 0px; 
    height: 100%; 
    width: 100%;
    overflow: auto;
}
.table{
    background: pink;
    display: table;
    width: 100%;
    height: 100%;
}
.tableRow{
    display: table-row;         
}
.tableCell{
    display: table-cell;
    vertical-align: top;
    height: 100%;  
}
/*
    Ensures the full size of the table-cell has the behaviour of a block-element. 
    This is needed, because 'table-cell' will behave differently in different browsers.
*/
.tableCell>div{
    height: 100%;
}
/*
    Padding has to be used instead of margin in 'border-box' modus.
*/
.tableCell>div>div{
    height: 100%;
    box-sizing:border-box;
    -moz-box-sizing:border-box;
}
/*
    The final content.
*/
.tableCell>div>div>div{
    background: lightblue;
    padding: 5px;
    height: 100%;
    box-sizing:border-box;
    -moz-box-sizing:border-box;
}


#col1{
    width: 16.66%;          
}
#col1>div>div{
    padding-right: 10px;
}
#col2{
    width: 25%;         
}
#col2>div>div{
    padding-right: 10px;
}
#col3{      
    width: 16.66%;
}
#col3>div>div{
    padding-right: 10px;
}
#col4{
    width: 41.66%;
}

[〜#〜] html [〜#〜]

<div class="table">
    <div class="tableRow">
        <div id='col1' class="tableCell">   
            <div><div><div>16.66%</div></div></div>
        </div>
        <div id='col2' class="tableCell">
            <div><div><div>25%</div></div></div>
        </div>
        <div id='col3' class="tableCell">
            <div><div><div>16.66%</div></div></div>
        </div>
        <div id='col4' class="tableCell">
            <div><div><div>41.66%</div></div></div>
        </div>  
    </div>
</div>

追加のdivをわずかなマージンで使用するのはかなりやり過ぎですが、残念ながらCSSには「マージンボックス」モデルがなく、実際には10億の問題を解決できます。

この量のネストされたコードは、「他の手法を使用しない理由」を考えるかもしれません。コードが少なくなる可能性があるためです。非常に具体的な希望については、そうなるでしょう。ただし、他の手法では、多くの場合、浮動配置または絶対配置が使用されます。これらの手法は同じことを達成することはできません。たとえば、フロートは同じ長さの柱を実現できますが、境界線やマージンが必要な場合は問題が発生します。絶対配置の場合は逆になります。マージンの問題は解決できますが、高さは1列のみに基づいて決定できます。

私の意見では、CSSは要件を満たしていません。 positiongのテーブルを置き換えることはお勧めですが、これらすべての年が経っても、同じ結果を得ることができません。 「聖杯の聖杯」のテーブル構造を達成するには、最も簡単な方法だけでなく、唯一の方法もあります...少なくとも、何百もの可能性を試した後は知っています。

残りの質問は、テーブルとして使用している場合、なぜdivを使用するのかということです。これは私自身を完全には理解していませんが、人々はその理由を持っているようです。

2
Kevin Driessen

純粋なCSS/HTML(JavaScriptを使用しない等間隔の「列」を持つ流体レイアウト)については、このスレッドでthirtydotの答えを確認してください...

等間隔のDIVを持つ流体幅

http://jsfiddle.net/thirtydot/EDp8R/

JSFiddleの変更は、「列」を異なる固定幅にでき、なおかつ均等で流動的なマージンを持つことができることを示しています。

http://jsfiddle.net/EDp8R/43/

最後に、均等で流動的なマージンを維持しながら、パーセンテージを使用する別の例。

http://jsfiddle.net/EDp8R/45/

私はこれが正確な解決策ではないかもしれないことを理解していますが、それはあなたをかなり近づけますと思います。

2
Sparky

このためにOOCSSのグリッドを使用します

https://github.com/stubbornella/oocss

オンラインでは適切な例がないため、最近自分のサイトでデモをオンラインで公開しました:(

http://www.leipeshit.com/awesome_stuff/oocss/core/grid/grids_all.html

同じ効果を得るための簡単な方法は、列自体にマージン/パディングを適用するのではなく、列内のコンテンツに溝を作成させることです。これは、固定グリッド、流体グリッド、弾性グリッドなどで実行できます。

例えば:

/* Gutters */
h1, h2, h3, h4, h5, h6,
p, ul, ol, blockquote,
hr, address, pre, object, fieldset
{
    margin-right: .75rem;
    margin-left: .75rem;
    padding-right: .75rem;
    padding-left: .75rem;
}

これにより、列のサイズ変更、ネスト、およびレゴピースへの背景の適用も簡単になります。

1
BBQ Brains

親要素の幅に関係なく、すべての列にわたって固定された一貫したマージンを持つ行内の柔軟な列の任意の組み合わせを可能にするこの代替ソリューションを最近開発しました。

これはJavaScriptを使用せず、IE8 +で動作します。

このソリューションでは、マージンは2つのクラスで定義されているため、レスポンシブデザインに合わせて簡単に変更できます。列幅は、使用するスペースも表します。たとえば、2列の行の幅は50%で、4列の行の幅は25%です。

http://www.andrewjamestait.co.uk/conflexgrids/ で例を見ることができます

または、GitHubの https://github.com/andrewjtait/conflexgrids で入手できます。

0
Andrew Tait

最初の例のようにパディングを使用してから、すべての要素にbox-sizing:border-boxを設定しないのはなぜですか?

0
Jonas Grumann

列ごとに別のネストされたdivを使用できる場合は、それぞれに必要なマージンを定義できます。左右の外側の端のマージンを取り除くために、外側のコンテナに負のマージンを定義できます。

例: pureCSS を使用すると、pure-gは外部コンテナ、pure-u- *はネストされたdivを含む列ノード(表示:インラインブロック)です。間隔は、列マージンを許可するためのpureCSSグリッドシステムのこのカスタム拡張の名前です。

.pure-g.spacing {
    margin: 0 -10px;
}

.pure-g.spacing [class *= "pure-u"] > div {
    margin: 10px;
}

ほとんどのブラウザで動作するはずです。そうでない場合は教えてください-私はすでにそれを使用しています。

よろしく、マックス

0
mxg