概述
前端开发中,页面布局很多时候是通过 css 属性搭配特定结构的 html 标签实现的。常见的结构有:容器(container)、包裹容器(wrapper)、内部容器(inner),以及内容(content)。
有一种流行的说法是 html 表达内容与结构(这里的结构只用于表达内容的包含或并列关系,与布局无关),css 表达样式,js 表达行为(本文不讨论 js )。由于 html 和 css 自身的限制,html 必须包含一定程度的与布局样式相关的标签,否则布局样式很难定位到 html 标签上,或者会难以维护。比如常见的浮动布局,需要给部分子元素添加浮动样式,同时在父元素上添加清除浮动的样式。若页面中只有代表页面区域和内容的标签,可能不一定正好有一个这样的父元素。
此外, H5 很早就提出了语义化标签的概念,方便开发者、计算机系统或设备更容易理解和使用网页的内容。在后台项目开发中,对语义化的要求或许不那么高,但前台项目由于是面向大众和整个互联网系统,因此,保留网页的语义化就显得不可或缺。因此,如何在实现布局的同时保留语义化也是值得思考的。
本文基于日常实践,整理出一些实现页面布局的常用思路,同时兼顾语义化。
容器结构的布局
布局的重点是确定内容在页面中的(平面)位置。基于内容结构,一层层分解下来,先确定容器的尺寸和位置,然后才能确定子元素的尺寸和位置。
上文提到了四层结构,但开发时并不是完全按照从上至下或从下至上的顺序实现。
一种可能的思路是:先确定整体布局和尺寸,再填入内容,接着抽象出各区域的同类布局结构,最后是特定区域或内容的特定布局。也就是先确定 html 自身最重要的内容结构,然后再根据布局要求,加入代表布局的结构。
一、实现页面的内容结构
- 根据页面主体的内容,划分出大的区域,并使用语义化结构标签,比如常规的 header、nav、main、aside、footer 等。
- 在大的区域中继续根据内容,划分出中等区域(这些区域的内容和/或样式,应当具有视觉上的明显区别);若中等区域内部仍有一些不同的内容,可以继续划分为小区域,直至区域内容具有高度相关性(比如一个列表、段落、表格或表单等)。
- 在区域中根据实际内容,选择合适的语义化内容标签,如 ul/li、form/input/button、table/thead/th/td 等。
以上 1、2 步骤中,区域划分好之后可以加上各区域的固定尺寸,或者继承父元素的尺寸或由内容自动撑开。
二、实现页面区域的布局结构
-
根据页面的整体布局,确定页面主体与视窗的关系,并抽象出顶层布局结构。如常见的居中式布局,页面的大部分甚至全部内容都位于页面中间的固定宽度之内,两侧分别留有自适应空白区域。这类布局的一种实现思路是:
三层结构(container > wrap > content):
container 与视窗同宽(100%)
wrap 为固定宽度(如 1200px)
content 与 wrap 同宽(100%)然后将三层结构套在 一、 中得到的页面主体内容的外层。
其中,第一层 container 可以与 section 标签结合,改为 section-list,此时 content 可同步改成 section-item,比如 header 中全宽的多行结构(背景全宽,内容还是居中);或者,可以将 content 与 section 标签结合,比如 main 标签里整体居中的多行结构。
当然,对于多数后台项目,内容都是占满整个视窗的,因此可以省去第一步。 -
与 1. 的思路相同,继续抽象出大的区域以及更小区域内的同类结构,根据各自布局规则分成若干分组,并针对不同的分组设置各自独立的布局样式,也就是有默认布局和其他多种布局,只是会作用于不同层级的相同结构。常见的如 title + content + extra 结构(类似于 header + main + footer),可以给不同的分组设置不同的内外边距、子元素的间距等,当然也包括颜色尺寸等属性。
内容的布局
完成容器结构的布局后,接下来针对所有最低一级区域,实现内容的布局样式。比如列表的多行、多列等间距布局,内容的水平垂直居中或左右对齐等。
思路同样是先抽象出相同的布局样式作为公共或默认布局,再针对特定区域设置新布局以覆盖公共或默认布局。
概念介绍
在介绍内容布局的实现之前,先理清一些重要概念。
布局对象
布局对象可分为:块级元素、(内容非文本的)行内元素(或叫内联元素)、文本与符号(这里的文本指的是 innerText 部分,而非包含文本的 span 等标签)。由于文本/符号布局的特殊性和复杂性,将其单独归为一类。
此外,还有一个特殊的行框,也就是 line-height 确定的区域,内联元素和文本/字符默认是在行框中垂直居中
同时,由于 css 布局是基于盒子模型,因此所有的尺寸都是作用于元素的“盒子”,且布局结果都是表现在容器元素的子元素上,不存在脱离容器的布局一说。即使是位于最外层的 div 元素,也仍有 html 和 body 两层容器。
布局方式
容器内元素的布局方式包括:
- 排列方式:
- 水平(行内元素的默认)
- 垂直(块级元素的默认)
- 多行元素/文本换行
- 对齐方式:
- 单边对齐:上/下/左/右对齐
- 双边对齐:水平或垂直居中,两端对齐(对于元素, float 的 left + right 或 flex 的 space-between/around/evently;对于文本,text-align[-last]: justify)
- 四边对齐:水平垂直居中
常见布局(这里不谈流式布局、响应式布局等布局的设计和应用方式,只讨论 css 本身支持的布局方式属性):
- 默认的文档流(可以视作默认布局)是垂直块+水平内联的模式。
- 浮动布局会使得元素成为块级并脱离文档流,并使之后的元素一起浮动产生水平排列的效果;对于浮动盒子周围的文本则会产生文本包围盒子的效果。
- 弹性盒子布局支持多行多列,且支持间距的批量自定义。不同的行/列之间不要求对齐。
- 网格布局也支持多行多列和间距的批量自定义。但比起弹性盒子,网格布局更强调行列的对齐。
- 定位布局与上述布局不太一样:相对定位是在元素原位置的基础上平移,绝对定位是基于某个容器平移,固定定位是基于视窗平移,而粘性布局是基于滚动行为和视窗的动态固定。通常是用于调整特定元素的位置,而非批量布局。
确定元素的位置
正如上文提到的,要确定元素的位置,需要知道元素的尺寸和间距。
根据元素的类型,可以将尺寸相关属性分为以下几类:
- 容器尺寸(包括块级元素和非文本行内元素):width/height
- 文本尺寸:font-size
布局的间距包括:
- 容器的内外边距:margin、padding
- 块级子元素的间距:这个没有特定的属性,通常是通过 margin 实现固定间距,或者通过 Flex/Grid 实现间距的自适应
- 非文本行内子元素的间距:同上块级子元素的间距
- 文本/字符的间距:行间距(line-height)、字间距(letter-spacing、word-spacing)、缩进(text-indent)
知道了有哪些属性可用,接下来就是根据设计稿确定应该用什么属性以及具体的属性值。
选择属性和确定属性值
首先确定内容和包裹内容的元素的尺寸,以及同级内容(也就是兄弟元素)的间距:
- 对于块级元素这很简单,只要知道各元素的显示宽高,静态元素直接代入 width/height,动态元素根据元素的排列方向确定是使用固定宽高或是由内容撑开。比如一个水平排列且支持换行的列表,其宽度应该是确定的,但高度有内容撑开。
- 对于行内元素,只给有需要的元素设置宽度即可,因为宽度会自动撑开。对于内容非文本的行内元素,一般不需要设置行高,有高度即可。
- 对于文本/字符,首先确定字号,然后根据多行文本的间距确定行高。
内容的尺寸和间距确定好之后,接下来是根据其在容器内的位置,计算出容器与子元素的间距。个人习惯先使用 padding 填充四边相同的间距,若是不足的再在子元素上加 margin 补全;若是子元素与容器的间距都不同,也是先填充 padding,然后将不足的间距加到对应的子元素 margin 属性上。
总结
以上都是基于个人经验的总结,可能有不合理的地方或是遗漏之处。主要是想规范一下布局的实现,减少反复修改。
标签:布局,间距,通用,元素,内容,思路,文本,页面 From: https://www.cnblogs.com/cjc-0313/p/16829114.html