浅谈css的栅格布局
栅格布局想必大家都很了解,我们做页面开发的时候,往往对页面板式的要求很高,如何对各个区域的内容排版,并使之对齐是我们的一大难题。而栅格系统就是我们排版的利器,他支持自动对齐、自动计算边距、流式布局等优点,简单好用的特性使得栅格布局成为所有主流框架的必备的功能。
我们简单分析一下栅格布局的原理:
容器/行/列/栅间距
一个栅格布局需要3部分组成——容器(container),行(row),列(column,也可称为栅)。容器是用于确定宽度的,行需要放到容器中;行是将列分组,并把一组列合并为一个行;列是正真的显示内容的元素,我们的内容就写在列里面。具体可参考下图
如果仅是行与列来布局,自适应布局也能满足需求,栅格布局的高明之处在于它还提供了列与列之间存的间距,我们称之为栅间距(gutter),栅间距仅存在列与列之间,列和容器之间是不应该存在栅间距的。栅间距的存在使得我们不用自己去计算padding,设置布局更加简单,对齐也更加容易。
列宽
完善的栅格布局框架,都会提供一个类似自适应布局一样的声明列宽的class类。首先系统把容器分为若干份,这个总份数一般都是3、4的倍数,这样利于排版。然后再提供若干代表份数的类,让列去继承,这样列就会占据容器总宽度的指定份数(span)了。如上面我们的例图,容器的总份数是9,各个列继承不同的份值,并保证了一行里面的所有列的份值相加也是9。
栅格嵌套
同时栅格系统是可以嵌套的,即列里面也可以作为容器,里面可以再声明一行,然后继续声明子列,这种行为我们称之为栅格嵌套,如下图:
列的换行行为
早期的栅格系统框架,列与列之间是不能换行的,即一行中的所有列都必须确保在同一行中。但是随着响应式布局的兴起,一行中的列也需要出现换行行为,而且换行后也没不能出现显示错误,这种行为我们称为列的换行行为,如下图。因为涉及栅间距的计算,所以不是每一个栅格系统都可以支持“列的换行行为”的。列的换行行为对于完成响应式布局非常重要的,最为明显的例子就是bootstrap3的响应式功能要远远比bootstrap2强大,原因就是因为bootstrap3的栅格支持“列的换行行为”。
列宽的计算
根据上面我们对原理的分析,可以看出,如何计算栅间距是栅格系统的核心。没有了栅间距,栅格布局也就成了普通的自适应布局,那么如何去计算栅间距、列宽、行宽的关系呢?从栅格系统的表现形式可以看出,一行中栅间距的个数等于总份数减一。如果容器的宽度是width,总份数是n,列间距的宽度是gutter,列的份数是span,列宽是colwidth。那么有:
colwidth = (width + gutter) / n * span - gutter
这个计算并不复杂,但是想要通过css2去自动计算几乎是不可能的。
同时栅格系统还有一个难点,就是如何控制哪个列有栅间距,哪个列没有。css中控制元素与元素之间的间隔用的是margin,而且栅格与容器之间是没有栅间距的,因此每个列的margin计算就是另一个难题。
这两个问题很难直接用css2解决,但是使用一些黑科技还是可以解决这两个问题。如果是面向的浏览器支持css3,利用css3的语法解决这两个计算问题也是可行的。根据市面上的几个流行框架,笔者大致总结出了确定列宽、栅间距的几种方法:
1.固定container宽度法
这个方法比较简单,首先框架要确定容器的宽度,这样因为容器的宽度是固定的,就可以计算出列宽了。
至于栅间距的确定也十分简单,就是让开发人员自己去设置。框架在每一列都设置一个向左或者向右的margin,然后再定义一个最后一列或者第一列的样式类(如“.first”或者“.last”),通过开发人员手动设置这个样式类,将最后一列(或者第一列)多出来的margin去除掉。
如果浏览器支持css3,可以用css3的伪类“:last”和“:first”代替人工设置法的“.last”和“.first”,这样更加自动化一些。
这种方法是不支持“列的换行行为”,因为一旦出现了一行被挤到了第二行,他的栅间距的计算就会出现问题。即便是用伪类去辅助计算行间距,仍然无法去除换行后元素的多出来的栅间距。
总结:这种方法好处是简单,兼容性好。缺点是仅支持固定的container,适用性很差,同时还不支持列的换行行为。
代表框架:蓝图(blueprint)
2.行单向偏移法
这个方法非常巧妙,使用很简单的方法将列宽度和栅间距的确定问题解决列,思路上是这样的,因为一行中栅间距的个数等于总份数减一,如果把让行宽等于容器的宽度加上一个栅间距,那么一行能容纳的行间距的个数刚好等于总份数,这样计算列宽也简单了。具体可参考下图
这个方法巧妙在通过扩充行的宽,并使-margin的方法使之再偏移之一个栅间距的距离,这样多出一个不影响列显示的栅间距,使整个栅格系统的计算变得非常简单。
使用这个方法的另一个好处就是,他支持“列的换行行为”。我们之前说过“列的换行行为”是完成栅格的响应式布局的重要特性,使用行偏移法,我们不需要去控制个别列的padding或者margin的行为,这样使得列在换行后仍能正常显示成为可能。
当然这种方法也存在缺点,就是如何确定扩偏移后的行的宽度。因为偏移后的行的宽度要正好等于栅间距加上容器宽度,如果不使用css3的calc是很难的,也只能在用在固定容器宽度的情况下才能算出。
另外一个问题就是列宽的计算要使用padding和box-sizing属性,这使得我们需要多声明一个元素用于布局,这样一个栅格布局中就会多声明两层元素去用于布局,文档的语义化会减弱,而且一旦栅格嵌套,就会产生更多的无用的dom。
代表类库:bootstrap2的栅格就是使用这个方式,因为bootstrap2的栅格系统容器是定宽的,所以列宽就可以通过less事先计算好,这样就可以省去列通过padding计算列宽的步骤,使得栅格系统更加简洁。
3.行双向偏移法
这个方法是目前最流行方法,相当于利用了一个黑科技来完成这个艰巨的任务。这个方法和上一个“行单向偏移法”非常相似,只是因为行单向偏移法存在难以计算实际行宽的问题,而双向偏移法就是为了解决这个问题而诞生的。
方法是向左右各偏移半个栅间距,利用偏移后的效果由浏览器自动去计算行实际的行宽,而不是指定行宽。我们知道块级元素的宽度表现特性为:块级元素的宽度默认会占满整个容器,如果元素定义了margin,那么宽度将是父容器宽度去除margin后的宽度。即使margin是负值,这个计算方法同样适用,这其实是个hack,但是这样就可以利用来解决行宽的计算问题。具体方法如下图:
目前很多流行框架都使用这个方法,不过这个方法笔者很不喜欢,因为这样列也成为了一个布局元素,想要完成一个布局,要多生成三层元素,感觉这样做很不值得。不妨我们看看bootstrap3中文官网的dom结构,看看他那复杂的令人发狂的dom树你就会对这个方法的感到失望。不过不管怎么说他都很棒的解决列栅格系统的两大难题
代表类库:妹子ui、bootstrap3、Foundation
4.使用calc计算法
calc属性是css3中最令人着迷的属性之一,以往ie浏览器也提供过类似calc这种可计算的属性的方法,但是因为效率低下并且是非标准语法,一直被大家拒之门外。而calc的到来,终于让css中运用数值运算来计算尺寸成为可能。
我们之前分析出的公式直接使用calc上运算就行,因为calc是支持百分比与有单位的数值进行运算的。
当然,这仅是解决列列宽的问题,例如如何实现“列的换行行为”的问题还是没有解决,因此这个方法可以和“行单向偏移法”一起使用。
当然calc方法的最大缺点就是兼容性问题,ie低版本和诸多移动端浏览器都不支持这个属性,因此目前还没见过哪个主流框架是使用calc来实现栅格系统的。不过未来在各大主流浏览器均支持calc后,使用calc开发栅格系统必将成为主流,因为这个方法比起上面的hack方法更加简单。
5.使用flex布局
一些移动框架开始使用flex来提供栅格布局,不过flex布局并没有和上述几种方法有什么不同,原理上也是上述的4种形式,仅是用flex代替列float而已。不过在垂直方向上,flex利用自身特性,提供了一套垂直对齐的模式,算是对栅格系统进一步的补充。
代表类库:ionic
总结
栅格布局的实现方法主要就是上述的几种,了解列这些方法,我们就可以自己开发属于简单的栅格系统,从而不再依赖那些又大又笨的样式框架,使我们的项目更加坚定干净。
浅谈css的栅格布局的更多相关文章
- 转:浅谈CSS在前端优化中一些值得注意的关键点
前端优化工作中要考虑的元素多种多样,而合理地使用CSS脚本可以在很大程度上优化页面的加载性能,以下我们就来浅谈CSS在前端优化中一些值得注意的关键点: 当谈到Web的“高性能”时,很多人想到的是页面加 ...
- CSS实现栅格布局
CSS实现栅格布局 设置容器container: .grid-container { width: 100%; max-width: 1200px; } 清除浮动: .row:before, .row ...
- 浅谈CSS模块化
为什么要CSS模块化? 你是否为class命名而感到苦恼? 你是否有怕跟别人使用同样class名而感到担忧? 你是否因层级结构不清晰而感到烦躁? 你是否因代码难以复用而感到不爽? 你是否因为commo ...
- 浅谈css的伪元素::after和::before
css中的::after和::before已经被大量地使用在我们日常开发中了,使用他们可以使我们的文档结构更加简洁.但是很多人对::after和::before仍不是特别了解,究竟他们是做什么的?如何 ...
- 浅谈CSS布局
在No.4中谈及了下盒子模型,引出布局模型 1.布局模型有三类: 1)流动模型 flow(默认) 2)浮动模型 float 3)层模型 layer 2.文档流 :指的是文本沿着从左到右的方向展开 ...
- [浅谈CSS核心概念] CSS布局模型:float和position
1.流动模型 HTML元素在默认情况下都是按照"流动模型"进行布局的,网上也有人称之为"普通流"."文档流"之类的.这种布局模式的特点在于: ...
- 浅谈css中的盒模型(框模型)
css中的盒模型是css的基础,盒模型的理解可以帮助我们进行对样式进行修改.废话不多说,进入正题: 在w3c中,CSS 框模型 (Box Model) 规定了元素框处理元素内容.内边框.边框 和 外边 ...
- 浅谈CSS盒子模型
[摘要]盒子模型是CSS中的一个重要概念,虽然CSS中没有盒子这个单独的属性对象,但它却是CSS中无处不在的一个重要组成部分.掌握盒子模型的原理和使用方法可以极大地丰富HTML元素的表现效果,同时对于 ...
- 浅谈CSS hack(浏览器兼容)
今天简单写一点关于浏览器兼容的处理方法,虽然百度上已经有很多,但是我还是要写! 先看一个图 这个图描述了2016年1月至8月网民们所使用的浏览器市场份额(来源:http://tongji.baidu. ...
随机推荐
- PHP实现RTX发送消息提醒
RTX是腾讯公司推出的企业级即时通信平台,大多数公司都在使用它,但是我们很多时候需要将自己系统或者产品的一些通知实时推送给RTX,这就需要用到RTX的服务端SDK,建议先去看看RTX的SDK开发文档( ...
- .NetCore中的日志(2)集成第三方日志工具
.NetCore中的日志(2)集成第三方日志工具 0x00 在.NetCore的Logging组件中集成NLog 上一篇讨论了.NetCore中日志框架的结构,这一篇讨论一下.NetCore的Logg ...
- 小白解决CENTOS7错误:Cannot find a valid baseurl for repo: base/7/x86_6
刚入手的MacBook想着学点东西,本汪还是决定玩玩CentOS服务器,安装好了VirtualBox + CentOS. 打开一看,懵逼了!命令行! 行吧,先装个图形界面: $sudo yum gro ...
- angular实现统一的消息服务
后台API返回的消息怎么显示更优雅,怎么处理才更简洁?看看这个效果怎么样? 自定义指令和服务实现 自定义指令和服务实现消息自动显示在页面的顶部,3秒之后消失 1. 显示消息 这种显示消息的方式是不是有 ...
- Python列表去重
标题有语病,其实是这样的: 假设有两个列表 : L1 = [1,2,3,4] ; L2 = [1,2,5,6] 然后去掉L1中包含的L2的元素 直接这样当然是不行的: def removeExists ...
- HTML文档头部
前面的话 在声明文档类型之后,HTML文档的下一部分为<html>标签,告知浏览器应将括在<html>...</html>内的所有内容解析为HTML.然后是HT ...
- python笔记(持续更新)
1.编译python遇到下面的编码问题: SyntaxError: Non-ASCII character '\xe9' in file E:\projects\learn.py on lin ...
- 讓TQ2440也用上設備樹(1)
作者:彭東林 郵箱:pengdonglin137@163.com QQ:405728433 開發板 TQ2440 + 64MB 內存 + 256MB Nand 軟件 Linux: Linux-4.9 ...
- spring boot 部署为jar
前言 一直在ide中敲代码,使用命令行mvn spring-boot:run或者gradlew bootRun来运行spring boot项目.想来放到prod上面也应该很简单.然而今天试了下,各种问 ...
- 解决“chrome提示adobe flash player 已经过期”的小问题
这个小问题也确实困扰我许久,后来看到chrome吧里面有人给出了解决方案: 安装install_flash_player_ppapi, 该软件下载地址:http://labs.adobe.com/do ...