CSS布局

1. 正常文档流(Normal Flow)

  • 默认情况下页面使用的正常流(normal flow)进行排版
  • 在正常流中,元素盒子(boxes)会基于文档的写作模式(writing mode)一个接一个地排列

2. 浮动(Float)

浮动用于将盒子置于左边或者右边,同时内容环绕。
要让一个元素进行浮动,需要为该元素设置一个值为leftrightfloat属性。默认值为none

.item {
    float: left
}

值得强调的是,当你使某个元素浮动并让文字环绕它时,内容的line box被截断了。如果你让一个元素浮动,同时为紧跟着的包含文本的元素设置一个背景色,你会发现背景色会出现在浮动元素下方。

如果你想要在浮动元素和环绕的文本之间创建边距,你需要给浮动元素设置外边距。在文本元素上设置外边距只会让其相对于容器缩进。例如在下面这个例子中,你就需要为左侧浮动的图片设置右边距和下边距。

<div class="container">
  <div class="item"></div>
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.item {
  width: 100px;
  height: 100px;
  float: left;
  margin: 0 20px 20px 0;
  background-color: rgba(111,41,97,.3);
}

2.2. 清除浮动

使用浮动后它后面所有接下来的元素都会环绕它直到内容处于它下方且开始应用正常文档流。如果你想要避免这种情况,可以手动去清除浮动。

添加clear属性即可。使用left值可以清除左浮动效果,right值为右浮动,both则会清除左右浮动。

.clear {
    clear: both;
}

但是,当你发现在容器内有了一个浮动元素,同时容器文本内容过短时就会出现问题。文本盒子会被绘制在浮动元素下,然后接下来的部分会以正常流绘制在其后。

最常见的清除浮动的hack方案是:在容器内添加一个CSS伪元素,并将其clear属性设置为both。

<div class="container">
  <div class="item"></div>
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.item {
  width: 100px;
  height: 100px;
  float: left;
  margin: 0 20px 20px 0;
  background-color: rgba(111,41,97,.3);
}

.container::after {
  content: "";
  display: table;
  clear: both;
}

2.3. 块级格式化上下文(Block Formatting Context)

清除浮动的另一个方法是在容器内创建BFC。一个BFC元素完全包裹住了它内部的所有元素,包括内部的浮动元素,保证浮动元素不会超出其底部。创建BFC的方式有很多种,其中最常用的一种清楚浮动的方式是为元素设置除visible(默认)之外的overflow属性值。

.container {
    overflow: auto;
}

为了使清除浮动的意图更加直观,并且避免BFC的负面影响,你可以使用flow-root作为display属性的值。display: flow-root做的唯一的一件事就是去创建一个BFC,因此可以避免其他创建BFC方法带来的问题。

.container {
    display: flow-root;
}

2.4. 浮动的一些遗留用法

在新的布局方式出现以前,float经常会被用来创建多栏布局。我们会给一系列元素设置宽度并且将它们一个接一个进行浮动。通过为浮动元素设置一些精细的百分比大小可以创建类似网格的效果。

我不建议在当下仍然过度地使用这种方法。但是,在现有的网站中,这种方式仍然会存在许多年。因此,当你碰到一个页面里面到处是float的应用,可以确定它就是用的这种技术。


3. 定位(Positioning)

想要把一个元素从正常流中移除,或者改变其在正常文档流中的位置,可以使用CSS中的position属性。当处于正常文档流时,元素的position属性为static。在块级维度上元素会一个接一个排列下去,当你滚动页面时元素也会随着滚动

3.1. 相对定位(relative postioning)

如果一个元素具有属性position: relative,那么它偏移的参照位是其原先在正常文档流中的位置。你可以使用topleftbottomright属性来相对其正常流位置进行移动。

.item {
    position: relative;
    bottom: 50px;
}
  • 页面上的其它元素不会受到影响。该元素在正常流中的位置会被保留,因此你需要自己去处理一些元素内容覆盖的情况。
<div class="container">
  
  <p>Pea horseradish azuki bean lettuce avocado asparagus okra. Kohlrabi radish okra azuki bean corn fava bean mustard tigernut jícama green bean celtuce. </p>
  
  <div class="item"></div>
  <p>Grape silver beet  collard greens avocado quandong fennel gumbo black-eyed pea watercress potato tigernut corn groundnut. Chickweed okra pea winter purslane coriander yarrow sweet pepper radish garlic brussels sprout groundnut summer purslane earthnut pea tomato spring onion azuki bean gourd. Gumbo kakadu plum komatsuna black-eyed pea green bean zucchini gourd winter purslane silver beet rock melon radish asparagus spinach.</p>
</div>
body {
  padding: 20px;
  font: 1em Helvetica Neue, Helvetica, Arial, sans-serif;
}

p {
  margin: 0 0 1em 0;
}

.container {
  width: 500px;
  border: 5px solid rgb(111,41,97);
  border-radius: .5em;
  padding: 10px;
}

.item {
  width: 100px;
  height: 100px;
  background-color: rgba(111,41,97,.3);
  position: relative;
  bottom: 50px;
}

3.2. 绝对定位(absolute postioning)

给一个元素设置position: absolute属性可以将其完全从正常流中移除。其原本占据的空间也会被移除。该元素会定位会相对于视口容器,除非其某个祖先元素也是定位元素(position值不为static)。

因此,当你为某个元素设置position: absolute时,首先发生的变化是该元素会定位在视口的左上角。你可以通过设置topleftbottomright偏移量属性来将元素移动到你想要的位置。

.item {
    position: absolute;
    top: 20px;
    right: 20px;
}

通常情况下你并不希望元素相对于视口进行定位,而是相对于容器元素。在这种情况下,你需要为容器元素设置一个除了默认static之外的值。

由于给一个元素设置position: relative并不会将其从正常流中移除,所以通常这是一个不错的选择。给你想要相对的容器元素设置position : relative,就可以让绝对定位的元素相对其进行偏移。

3.3. 固定定位(fixed positioning)

大多数情况下,position: fixed的元素会相对于视口定位,并且会从正常文档流中被移除,不会保留它所占据的空间。当页面滚动时,固定的元素会留在相对于视口的位置,而其他正常流中的内容则和通常一样滚动。

.item {
    position: fixed;
    top: 20px;
    left: 100px;
}

为了使一个固定定位的元素不相对于视口进行定位,你需要为容器元素设置transformperspectivefilter三个属性之一(不为默认值none)。这样固定的元素就会相对于该块级元素偏移,而非视口。

3.4. STICKY 定位

设置position: sticky会让元素在页面滚动时如同在正常流中,但当其滚动到相对于视口的某个特定位置时就会固定在屏幕上,如同fixed一般。这个属性值是一个较新的CSS属性,在浏览器兼容性上会差一些,但在不兼容的浏览器中会被忽略并会退到正常的滚动情况

.item {
    position: sticky;
    top: 0;
}

4. 弹性布局(Flex Layout)

弹性盒子(Flexbox)布局是一种为一维布局而设计的布局方法。一维的意思是你希望内容是按行或者列来布局。你可以使用display: flex来将元素变为弹性布局。

.container {
    display: flex;
}

该容器的直接子元素会变为弹性项(flex item),并按行排列。

4.1. 弹性盒子的轴(axes)

在上面的例子中,我们会称弹性项在行内是从起始位置开始排列,而不是说它们是左对齐。这些元素会按行排列是因为默认的flex-direction值为rowrow代表了文本的行文方向。由于我们工作的环境是英文(中文也是如此),一种自左向右的语言,行的开始位置就是在左边,因此我们的弹性项也是从左边开始的。因此flex-direction的值被定义为弹性盒子的主轴(main axis)

交叉轴(cross axis)则是和主轴垂直的一条轴。如果你的flex-directionrow并且弹性项是按照行内方向排列的,那么交叉轴就是块级元素的排列方向。如果flex-directioncolumn那么弹性项就会以块级元素排列的方向排布,然后交叉轴就会变为row

4.2. 方向和次序

弹性盒子模型让我们可以通过为flex-direction属性设置row-reversecolumn-reverse值来改变主轴上弹性项的方向

example: Smashing Guide to Layout: flex-direction on Codepen

4.3. 一些Flex的属性

这些flex的属性是用来控制弹性项在主轴上空间大小的。这三个属性是:

  • flex-grow
  • flex-shrink
  • flex-basis
    通常可以使用它们的简写形式:flex。第一个值代表flex-grow,第二个是flex-shrink,而第三个则是flex-basis。
.item {
    flex: 1 1 200px;
}

flex-basis会为弹性项设置未拉伸和压缩时的初始大小。在上面的例子中,大小是200px,因此我们会给每个项200px的空间大小。但是大多数情况下容器元素大小不会正好被分为许多200px大小的项,而是可能有一些不足或剩余空间。flex-grow和flow-shrink属性允许我们在容器大小不足或有空余时控制各个弹性项的大小。

如果flex-grow的值是任意的正数,那么弹性项会被允许拉伸来占据更多的空间。因此,在上面的例子中,当各项被设为200px后,所有多余的空间会被每个弹性项平分并填满。

如果flex-shrink的值为任意的正数,那么当弹性项被设置了flex-basis后,元素溢出容器时会进行收缩。在上面这个CSS的例子中,如果容器空间不足,每个弹性项会等比例缩放以适应容器的大小。

flex-growflex-shrink的值可以是任意的正数。一个具有较大flex-grow值的弹性项会在容器有剩余空间时拉伸更大的比例;而一个具有更大flex-shrink值的项则会在容器空间不足时被压缩的更多。

理解这些属性是理解如何使用弹性布局的关键,下面列出的一些资源会帮助我们进一步学习其中的细节。当你需要在容器的一个维度上拉伸或者压缩一些元素时,你可以考虑使用弹性盒子模型。如果你发现你正尝试在行和列两个维度上排列你的内容,你需要的是网格模型(grid),这时弹性盒子模型很可能不是最合适的工具了。


5. 网格布局(grid layout)

CSS网格布局(grid layout)是一种用来进行二维布局的技术。二维(two-dimesional)意味着你希望按照行和列来排布你的内容。和弹性盒子类似,网格布局也需要设置一个display值。你可以为容器元素设置display: grid,并且使用grid-template-columnsgrid-template-rows属性来控制网格中的行与列。

.container {
    display: grid;
    grid-template-columns: 200px 200px 200px;
    grid-template-rows: 200px 200px;
}

作者:AlienZHOU
原文链接:https://juejin.im/post/5b3b56a1e51d4519646204bb
来源:掘金

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,390评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,821评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,632评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,170评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,033评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,098评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,511评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,204评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,479评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,572评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,341评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,893评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,171评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,486评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,676评论 2 335

推荐阅读更多精彩内容

  • 1. 前言 前端圈有个“梗”:在面试时,问个css的position属性能刷掉一半人,其中不乏工作四五年的同学。在...
    YjWorld阅读 4,402评论 5 15
  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,703评论 1 92
  • 前言 温馨提示:本文较长,图片较多,本来是想写一篇 CSS 布局方式的,但是奈何 CSS 布局方式种类太多并且实现...
    sunshine小小倩阅读 3,097评论 0 59
  • 一般而言,一个静态web页面的呈现需要通过html和css配合实现。html相当于页面的骨架,规定了文档的结构。c...
    夏木与晴空阅读 1,044评论 0 3
  • 一大早,欣喜地发现,Merry同学已经表演新概念到了47课,Tyger感到无比地开心和自豪。给你写这份信,是想站在...
    Tyger老师阅读 311评论 3 3