ホームページ >ウェブフロントエンド >htmlチュートリアル >3カラム適応幅レイアウトからCSSへの議論_html/css_WEB-ITnose

3カラム適応幅レイアウトからCSSへの議論_html/css_WEB-ITnose

WBOY
WBOYオリジナル
2016-06-24 11:32:441005ブラウズ

左右に 100 ピクセル、中央がブラウザの幅に適応する 3 列のアダプティブ レイアウトを実装するにはどうすればよいですか?

最初に思いつくのは、テーブル レイアウト を使用し、テーブルの幅を 100% に設定し、3 つの TDS、最初と 3 番目の固定幅を 100 ピクセルに設定し、中央の幅をアダプティブにすることです。リアルタイムデモ:

中央

ただし、テーブル レイアウトは、CSS が普及する前に使用されていたレイアウトであり、テーブルが読み込まれる前にテーブル全体が空白になり、ページがわかりにくくなるなど、多くの欠点があります。表のレイアウトや組版を変更するのは非常に面倒で困難です。

テーブル レイアウトを使用しない場合の 2 番目のアイデアは、以下に示すように、float を使用して、左の div を左にフロートし、右の div を右にフロートさせることです:

アクション 1 まず、左と右の div をフロートにします。

左フロート

右フロート

中央に div が 2 番目にランクされている場合:

<div style="float:left;">left</div><div>middle</div><div style="float:right;">right</div>

その結果は次のようになります:

アクション 2 右の div が 2 番目にフロートされます。行

中央

div のデフォルト表示はブロックであるため、幅が設定されていない場合、ブロックレベルの要素は可能な限り多くの水平スペースを占有します。 width: 200px が設定されている場合、効果は次のようになります:

アクション 3 右側の div は引き続き 2 行目にフロートします

float left

middle

right

float であるため、3 番目の div は依然としてラップされます。 right 現在の行のできるだけ右に配置されます。つまり、コンテナ ボックスの端またはその隣にある前の float 要素です。現在の行にスペースがない場合は、移動を続けます。十分なスペースができるまで押し下げます。真ん中はブロックボックスなので、widthを設定しても現在の行のスペースが占有されてしまいますので、右は次の行までのスペースしか取れません。

同時に、真ん中は200pxに設定されているのに、左側は幅100pxのように見えることに気づきました。これは、フロート要素は通常のドキュメント フロー内にありますが、隣接する (非フロート) 要素のコンテンツを周囲に配置することのみが可能であり、依然として隣接する要素の背景と境界スペースを占有するためです。中央に白い境界線を追加すると、次のようになります。

アクション 4 フローティング要素は、ドキュメント フロー内の対応する要素の背景とエッジ スペースを占有します

float left

middle

right

当然のことなので、float left 要素が中央の背景と境界線のスペースを占め、中央のコンテンツが左側の周囲に配置されます。これを理解することが重要です。

真ん中に p タグがあり、p タグの内容が比較的長いとすると、周囲のエフェクトは次のようになります。

アクション 5 フローティングサラウンドエフェクト

float left

middle

いったん周囲の要素float 要素を超えます 高さ以降は通常の幅で表示されます

float right

上で述べたように、float 要素の行では、隣接する要素のコンテンツの幅が調整されて短くなりますfloat 要素が占める幅まで拡大し、float 要素の面積を超えると、隣接する要素のコンテンツ表示幅は通常になります。

デフォルトの div は 1 行を占めるため、中央を 2 番目の div に配置することはできませんが、3 番目の div に配置する必要があります。 2 番目の div と 3 番目の div の順序を変更します:

<div style="float:left;">left</div><div style="float:right;">right</div><div>middle</div>

float の右 div を最初にレンダリングし、次に中央の div をレンダリングします。左にレンダリングした後、左の行にはまだスペースがあるためです。これは、左にフローティングした後、現在の行の背景と境界のみを占有し、現在の行にはまだ多くのスペースがあるためです。 2 番目のステップは、左と同じになります。 同じ行、効果:

アクション 6 まず、左と右の div をレンダリングし、次に中央の div をレンダリングします

中央

中央の幅を設定しない場合、中央は左右を囲みます。左と同様に、右も中央のスペースを占めます。

アクション 7 中央の div が左と右の div を囲みます

~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ middle围绕着left和right环绕,同时left和right占据着middle的空间 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

       为了让middle和left/right中间有一个margin值,设置下middle的左右margin各为110px,这样就和左右和中间就各有10px的间距:

Action 8 设置中间div的margin值为100px + 10px

left 

right 

middle 设置margin: 0 110px;

       这种办法的优点是实现简单,支持性好。

       这种自适应宽度的原理是利用了float的围绕特性,占据自然文档流的background/border位置。这个围绕特性不仅会影响当前行的内容,还会影响下一行的内容,如下说明:

<p>第一段内容,略<img src="" style="<strong>float:left;</strong>"></img></p><p>第二段内容,略</p>

Action 8 float元素占据了下一行的空间

第一段落围绕着图片排列

图片的float属性也影响了第二段落,也就是说float会占据自然文本流相应位置元素的背景和边框,即使和float的元素不在同一行

 

       网上还有一种margin负值法。margin负值法的步骤是:第一步让中间的middle占100%的宽度,而middle的内容设置左右margin各为100px,这样就实现了middle居中自适应宽度的效果:

<div style="width:100%;">      <div style="margin: 0 100px;">middle</div></div>

middle

       接下来让left的margin-left值为-100%,由于这个比例是相对于浏览器窗口大小的,所以要是left和middle是在同一行的话,left就可以跑到middle的最左边。但是因为middle的容器盒是一个普通的div,会占据一整行,left就会排到下一行,这个时候设置margin-left为一个负数时就跑出屏幕了。所以让middle float一下,left就会排到第一行最左边,同时middle覆盖在上面:

<div style="width:100%; <strong>float:left</strong>;">      <div style="margin: 0 100px;">middle</div></div><div style="margin-left: 0">left</div>

middle

left

      从上面可以看到:这样实现,导致left的内容被挤出目标区域,因为正如上面所说,middle占据了left的背景空间,上面的情况是把它占满了,left内容只能overflow了。所以这样实现是有问题的,得让left也向左float一下,这样left就紧挨在middle后面了,由于middle占了100%的宽度,所以再让left向左边margin了-100%后,left就刚好在最左边了。

<div style="width:100%; float:left;">      <div style="margin: 0 100px;">middle</div></div><strong><div style="float: left; margin-left: -100%;">left</div></strong>

middle

left

       注意这里,虽然left float之后看起来也是被排到下一行了,但和默认的div独占一行是不一样的。float之后的left仍然和middle是同一行的,因为空间不足的时候,float只是把当前行盒的空间撑大,就和一个div块盒里面有很多个display为inline-block的行内级盒是同样的道理。例如:

<style>     button{ width: 150px; }</style><div style="width: 300px;">    <button>按钮1</button>     <button>按钮2</button>     <button style="margin-left: -200px;">按钮3</button></div>

     按钮3设置了一个很大的margin-left的负值后并不是跑到屏幕外了,而是在和其它两个按钮同一行的位置,显示如下:

按钮1 按钮2 按钮3

     注意,设置了float的元素并不是把display改成了 inline-block,大部份display的css计算值都变成了block,同时对原本是display: flex的没有改变:

指定值计算值 テーブル列グループブロックテーブルセルブロック表キャプションブロックtable-header-groupblocktable-footer-groupblockflexflex、ただし float はそのような要素には影響しませんinline-flexインラインフレックスただし、float はそのような要素には影響しませんotherunchanged

来自MDN

     由上表可看出,一个span设置了float: left/right之后,就不需要再设置成display: block/inline-block了,直接设置宽高即可。

     回归正题,left的div设置了margin-left: -100%之后就跑到左边去了,而right也是同样道理,将right的margin-left相应地设置为-100px,就跑到最右边去了:

<div style="width:100%; float:left;">      <div style="margin: 0 100px;">middle</div></div><div style="margin-left: -100%;">left</div><strong><div style="margin-right: -100px;"</strong>>right</div>

Action 9 margin负值法

middle

left

right

 

      下面讨论第三种方法,使用display: table-cell

      由于table的展示拥有自适应的特点,因此把需要自适应宽度的middle的display属性设置为table-cell。

<div style="float:left;">left</div><div style="float:right;">right</div><div style="display:table-cell;">middle</div>

      效果如下:

left

right

middle

      发现table-cell的宽度是根据内容自适应的,这里是要根据浏览器窗口自适应,因此给middle添加一个很大的width就可以了,例如width:2000px:

Action 10 让中间的div使用table-cell自适应宽度

left

right

middle

      由于ie6/7不支持display: table-cell,所以如果要支持ie6/7的话,就得用display: inline-block,ie6/7的inline-block和标准不一样,它是用来触发hasLayout特性,使元素拥有布局属性。作用在行内元素,可以使得宽高等设置生效,如果作用在块元素,仅是触发布局特性,还要再设置成inline才是行内块元素,如果不设置inline效果就跟table-cell很像。不一样的地方是:设置了width:2000px,导致太长会换行,因此得用ie6/7的hack,设置*width: auto重新改会width值就可以了:

<style>    .middle{         display: table-cell;         *display: inline-block; /* _和*开头的只有ie6/7会识别 */         width: 2000px;         *width: auto;    }</style><div style="float:left;">left</div><div style="float:right;">right</div><div class="middle">middle</div>

      但是笔者认为:为了互联网的美好,不要再兼容ie6/7了,甚至ie8。

 

      接下来,继续第四种方法,使用flex布局,十分简单:只需要将容器设置为display: flex,然后再设置middle的flex-grow为1即可:

<section style="display:flex;"></section><div>left</div>   <!--宽度为100,省略--><div style="flex-grow: 1;">middle</div><div>right</div>

Action 11 使用flex-grow自适应宽度

left

middle flex-grow: 1

right

      flex-grow: 1的作用是把middle的宽度置为flex容器的剩余宽度,就达到了自适应的目的。flex的使用不作全面介绍,详情可查看CSS-Tricks: A Complete Guide to Flexbox

      但是flex布局ie的支持性较差,具体查看caniuse.

 

      最后再分析另外一个自适应的例子,某个元素的宽度要根据其它元素的宽度自适应。如下图所示,排名的位数变化可能会很大,导致最右边的文字要自适应:

 

       根据上面的一番分析,这个例子就不难实现了,如下面的分析,p标签里的文字宽度就能自适应了:

      

    <div style="width:320px;">        <span style="width:14px;<strong>float:left;</strong>">排名</span>        <span style="font-size:40px;<strong>float:left;</strong>">89</span>        <br />        <img style="width:44px;height:44px;<strong>float:left;</strong>" src="..."></img>        <p>你的好友会编程的银猪在土壕榜中排名89</p>    </div>

      实际效果:

排名 1

你的好友会编程的银猪在土壕榜中排名1

排名 6783

你的好友会编程的银猪在土壕榜中排名6783

 

 

       使用float是最简单的,还可以尝试使用flex布局,主要用到flex-shrink属性,flex-shrink的作用是定义收缩比例,容器内的子元素的宽度和若超出容器的宽度时,将按比例收缩子元素的宽度,使得宽度和等于容器的宽度。如下所示,将前面三个span/img的flex-shrink设置为0,而p的flex-shrink设置为1,这样子使得溢出的宽度都在p标签减去,就能够达到p标签宽度自适应的效果。

   <style>        span,img{<strong> flex-shrink: 0;</strong> }        p{<strong> flex-shrink: 1; </strong>}   </style>    <div style="display:flex;width:320px;">                                       <span style="width:14px;">排名</span>        <span style="font-size:40px;line-height:45px;">89</span>                <img style="width:44px;height:44px;" src="..."></img>        <p>你的好友会编程的银猪在土壕榜中排名89</p>    </div>

      实时效果:

ランキング 89

あなたの友達のプログラムできる銀の豚はランキング リストで 89 位にランクされています

ランキング 1890

あなたの友達のプログラムできる銀の豚はランキング リストで 1890 にランクされています

上記の総合記事 オリジナルテーブルレイアウトを分析し、次にフロートレイアウト、テーブルセル、ネガティブマージン法、およびフレックスレイアウトを実装して、フロートのいくつかの特性に焦点を当てて適応幅の実装と原理を実現しました。上記の分析に誤りがある場合は、修正してください。

参考:

1. CSS Float 理論: 知っておくべきこと

2. CSS のトリック: 表示

5.モデル

inline block
inline-block block
inline-table table
テーブル行 ブロック
テーブル行-グループ ブロック
テーブル列 ブロック
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。