CSS

css的艺术

结构与布局篇

Posted by XX on August 14, 2019

通常实现一种UI效果,有很多种方式,如何用更简单得代码,更易维护的方式,更好的兼容性来实现,是本文探讨的核心.

1.弹性布局的简单封装

优势:兼容性极好,布局精准,布局元素不会消失在正常的文档流(相对于float布局,absolute布局)

流行的UI框架(例booststrap,elementUI),都会有layout布局,对于页面整体布局帮助很大,使用也很方便,但当具体到元素中的布局时,再使用layout布局会显得极其繁琐,并给页面添加了不必要的元素,使得文档流显得不够清晰.

这种情况下,个人的建议是自己封装常用的弹性布局来实现元素内的可自定义的布局,下例由scss简单封装

// 弹性布局常用的一些组合
@mixin common-flex($justify, $align) {
  display: flex;
  justify-content: $justify;
  align-items: $align;
}
//横向-靠左-居中弹性布局
.hulk-flex-start {
  @include common-flex(flex-start, center);
}

//横向-靠右-居中弹性布局
.hulk-flex-end {
  @include common-flex(flex-end, center);
}

//横向-居中-居中弹性布局
.hulk-flex-center {
  @include common-flex(center, center);
}

//横向-两边-居中弹性布局
.hulk-flex-between {
  @include common-flex(space-between, center);
}

//横向-均分-居中弹性布局
.hulk-flex-evenly {
  @include common-flex(space-evenly, center);
}

//竖直方向-居中-居中弹性布局
.hulk-flexcol-center {
  flex-direction: column;
  @include common-flex(center, center);
}

//子项无弹性不压缩
.hulk-item-noshrink {
  flex-shrink: 0;
}
//子项占满剩余空间
.hulk-item-grow {
  flex-grow: 1;
  flex-basis: 100%;
  overflow: hidden;
}

2.常见页面布局实现的几种方法:

微信截图_20190729110749

如图所示div1固定高度200px,要求div2高度占满页面剩余高度,页面高度可调节

解决这个问题最主要的是确定div2的高度

第一种方案:定位法:对div2设置样式

.div2{
 position: absolute;
 top:200px;
 bottom: 0;
}

备注:当同时使用top和bottom定位时,元素高度会自适应变化

第二种方案:sass的计算公式来实现

.div2{
height:calc( 100vh - 200px)
}

备注:100vh为当前窗口的高度,如果父元素不是页面,可以使用100%来代替.

3.紧贴底部的页脚

难题:

微信图片_20190729114117

在网页设计中,存在一个相当古老但又相当常见的问题,它是前端工程师绕不开的坎。这个问题可以简单地概括如下:有一个具有块级样式的页脚(比如它设置了背景或阴影),当页面内容足够长时它一切正常,而当页面较 短时(比如错误信息页面)就会出现问题,页脚不能像我们期望中那样“紧贴”在视口的最底部,而是紧跟在内容的下方。 这个问题不仅普遍存在,而且乍看起来确实相当简单。其实对于之前的css却是个隐蔽式的大坑,当然,现在的css已经可以完美解决这个问题

第一种方案:固定高度
<header>
<h1>Site name</h1>
</header>
<main>
<p>Bacon Ipsum dolor sit amet...</p>
</main>
<footer>
<p>© 2015 No rights reserved.</p>
<p>Made with ♥ by an anonymous pastafarian.</p>
</footer>
main {
min-height: calc(100vh - 100px - 50px);
/* 避免内边距或边框搞乱高度的计算: */
box-sizing: border-box;
}

如果header和footer的高度是固定的,那我们直接给main设置最小高度为sass计算公式值,就可以完美解决上述问题

第二种方案:更灵活的方案-flexbox对于此类问题是完美的选择
body {
display: flex;
flex-flow: column;
min-height: 100vh;
}
main { flex: 1; }

对body元素添加弹性布局和最小高度,main元素设置弹性填满剩余高度值

4.自适应内部元素

难题:

众所周知,如果不给元素指定一个具体的 height ,它就会自动适应其内容的高度。假如我们希望 width 也具有类似的行为,该怎么做呢?举个例子,假设我们用 HTML5 来标记图片元素,结构代码可能是这样的:

<p>Some text [...]</p>
<figure>
	<img src="adamcatlace.jpg" />
	<figcaption>
		The great Sir Adam Catlace was named after
		Countess Ada Lovelace, the first programmer.
	</figcaption>
</figure>
<p>More text [...].</p>

默认情况会是这样:

文本行比图片要宽多了。但我们实际上希望这个 figure 元素能跟它所包含的图片一样宽(图片的尺寸往往不是固定的),而且是水平居中的。如何让 figure 的宽度由它内部的图片来决定,而不是由它的父元素来决定呢?

微信图片_20190729114117

通常解决办法很多有很多副作用

例如:

„ 让 <figure> 元素浮动会让它得到正确的宽度,但同时也彻底改变了它的布局模式)。
„ 对 figure 应用 display: inline-block 会让它根据内容来决定自身的尺寸,但跟我们想要的方式还是不一样(参见图7-3)。此外,即使它的宽度计算方式与我们的期望一致,我们也很难继续完成水平居中的任务。我们需要对它的父元素应用 text-align: center ,然后对这个父元素的所有子元素( p, ul, ol, dl, ... )都设置一遍text-align: left 。
„ 当开发者走投无路时,就只能对 figure 应用一个固定的 width 或max-width 了,然后对 figure > img 应用 max-width: 100% 。可是这个方法无法充分利用有效空间;对于过小的图片来说,布局效
果也很突兀。此外,响应式也无从谈起。
解决方案:

最终效果

微信图片_201907291141

figure {
width: min-content;
margin: auto;
}

备注: min-content 这个关键字将解析为这个容器内部最大的不可断行元素的宽度(即最宽的单词、图片或具有固定宽度的盒元素)

5.精确控制表格列宽

难题:

尽管多年以前我们就不再使用表格来完成页面布局了,但表格在现代网站中仍然有其不可替代的位置,我们需要用它来实现统计数据、电子邮件、拥有大量元数据的列表等表格型数据。但对于不固定的内容来说,它们的布局其实是很难预测的。这是因为列宽根据其内容进行调整,即使我们显式地指定了 width ,也只能起到类似提示的作用

解决方案:
table {
table-layout: fixed;
width: 100%;
}

备注:我们只需要对 <table> 元素或其他具有 display: table 样式的元素应用这个属性即可。请注意,为了确保这个技巧奏效,需要为这些表格元素指定一个宽度(哪怕是 100% )。同样,为了让 text-overflow:ellipsis 发挥作用,我们还需要为那一列指定宽度。

本文参考《css揭秘》