39.前端基础-布局2
11.7 实现扇形、圆形
参考答案:
圆形:
border-radius圆角的四个值按顺序取值分别为:左上、右上、右下、左下。这里只设置一个值,代表四个角的取值都为为50%
原理:border-radius: 50% 弯曲元素的边框以创建圆。
由于圆在任何给定点具有相同的半径,故宽和高都需要保证一样的值,不同的值将创建椭圆。
<div class="circle"></div>
<style>
.circle {
border-radius: 50%;
width: 80px;
height: 80px;
background: #666;
}
</style>
扇形:
利用border-radius,实现90度角的扇形:
原理:
左上角是圆角,其余三个角都是直角:左上角的值为宽和高一样的值,其他三个角的值不变(等于0)。
<div class="sector"></div>
<style>
.sector{
border-radius:80px 0 0;
width: 80px;
height: 80px;
background: #666;
}</style>
- 绘制任意角度的扇形
<div class="shanxing shanxing1">
<div class="sx1"></div>
<div class="sx2"></div>
</div>
<!--*绘制一个85度扇形*/--p>
<div class="shanxing shanxing2">
<div class="sx1"></div>
<div class="sx2"></div>
</div>
<!--*绘制一个向右扇形,90度扇形*-->
<div class="shanxing shanxing3">
<div class="sx1"></div>
<div class="sx2"></div>
</div>
<!--*绘制一个颜色扇形 */--p>
<div class="shanxing shanxing4">
<div class="sx1"></div>
<div class="sx2"></div>
</div>
<!--/*绘制一个不同颜色半圆夹角 */-->
<div class="shanxing shanxing5">
<div class="sx1"></div>
<div class="sx2"></div>
</div>
<style>
.shanxing{
position: relative;
width: 200px;
height: 200px;
border-radius: 100px;
background-color: yellow;
}
.sx1{
position: absolute;
width: 200px;
height: 200px;
transform: rotate(0deg);
clip: rect(0px,100px,200px,0px); /*这个clip属性用来绘制半圆,在clip的rect范围内的内容显示出来,使用clip属性,元素必须是absolute的 */
border-radius: 100px;
background-color: #f00;
/*-webkit-animation: an1 2s infinite linear; */
}
.sx2{
position: absolute;
width: 200px;
height: 200px;
transform: rotate(0deg);
clip: rect(0px,100px,200px,0px);
border-radius: 100px;
background-color: #f00;
/*-webkit-animation: an2 2s infinite linear;*/
}
/*绘制一个60度扇形*/
.shanxing1 .sx1{transform: rotate(-30deg);}
.shanxing1 .sx2{transform: rotate(-150deg);}
/*绘制一个85度扇形*/
.shanxing2 .sx1{transform: rotate(-45deg);}
.shanxing2 .sx2{transform: rotate(-140deg);}
/*绘制一个向右扇形,90度扇形*/
.shanxing3 .sx1{transform: rotate(45deg);}
.shanxing3 .sx2{transform: rotate(-45deg);}
/*绘制一个颜色扇形 */
.shanxing4 .sx1{transform: rotate(45deg);background-color: #fff;}
.shanxing4 .sx2{transform: rotate(-45deg);background-color: #fff;}
/*绘制一个不同颜色半圆夹角 */
.shanxing5 .sx1{transform: rotate(45deg);background-color: #f00;}
.shanxing5 .sx2{transform: rotate(-45deg);background-color: #0f0;
</style>
11.8 旋转45度
参考答案:
CSS中使用rotate方法来实现对元素的旋转,在参数中加入角度值,旋转方式为顺时针旋转。
<!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8" />
5 <title>Transform旋转</title>
6 <style>
7 div {
8 width: 300px;
9 margin: 150px auto;
10 background-color: yellow;
11 text-align: center;
12 -webkit-transform: rotate(45deg); /* for Chrome || Safari */
13 -moz-transform: rotate(45deg); /* for Firefox */
14 -ms-transform: rotate(45deg); /* for IE */
15 -o-transform: rotate(45deg); /* for Opera */
16 }
17 </style>
18 </head>
19 <body>
20 <div>黄色div</div>
21 </body>
22 </html>
11.9 画 0.5px 的直线
参考答案:
- 使用scale缩放
<style>
.hr.scale-half {
height: 1px;
transform: scaleY(0.5);
}
</style>
<p>1px + scaleY(0.5)</p>
<div class="hr scale-half"></div>

Chrome/Safari都变虚了,只有Firefox比较完美看起来是实的而且还很细,效果和直接设置0.5px一样。所以通过transform: scale会导致Chrome变虚了,而粗细几乎没有变化。但是如果加上transform-origin: 50% 100%:
.hr.scale-half {
height: 1px;
transform: scaleY(0.5);
transform-origin: 50% 100%;
}
chrome现在的效果如下

- 线性渐变linear-gradient
<style>
.hr.gradient {
height: 1px;
background: linear-gradient(0deg, #fff, #000);
}
</style>
<p>linear-gradient(0deg, #fff, #000)</p>
<div class="hr gradient"></div>

inear-gradient(0deg, #fff, #000)的意思是:渐变的角度从下往上,从白色#fff渐变到黑色#000,而且是线性的,在高清屏上,1px的逻辑像素代表的物理(设备)像素有2px,由于是线性渐变,所以第1个px只能是#fff,而剩下的那个像素只能是#000,这样就达到了画一半的目的。
- boxshadow
<style>
.hr.boxshadow {
height: 1px;
background: none;
box-shadow: 0 0.5px 0 #000;
}
</style>
<p>box-shadow: 0 0.5px 0 #000</p>
<div class="hr boxshadow"></div>
- viewport
<meta name="viewport" content="width=device-width,initial-sacle=0.5">
其中width=device-width表示将viewport视窗的宽度调整为设备的宽度,这个宽度通常是指物理上宽度。默认的缩放比例为1时,如iphone 6竖屏的宽度为750px,它的dpr=2,用2px表示1px,这样设置之后viewport的宽度就变成375px。但是我们可以改成0.5,viewport的宽度就是原本的750px,所以1个px还是1px,正常画就行,但这样也意味着UI需要按2倍图的出,整体面面的单位都会放大一倍。
11.10 css 切换主题
参考答案:
方式一:主题层
这应该是实现主题功能的一种最常用的手段了。首先,我们的站点会有一个最初的基础样式(或者叫默认样式);然后通过添加一些后续的额外的CSS来覆盖与重新定义部分样式。
具体实现
首先,我们引入基础的样式 components.* 文件
@import "components.tabs"; @import "components.buttons"
其中 components.tabs 文件内容如下
.tab {
margin: 0;
padding: 0;
background-color: gray;
}
然后,假设我们的某个主题的样式文件存放于 theme.* 文件:
对应于 components.tabs,theme.tabs 文件内容如下
.tab {
background-color: red;
}
因此,我们只需要引入主题样式文件即可
@import "components.tabs"; @import "components.buttons" @import "theme.tabs";
这样当前的样式就变为了
.tab {
margin: 0;
padding: 0;
/* background-color: gray; */
background-color: red;
}
优点
- 实现方式简单
- 可以实现将主题应用与所有元素
缺点
- 过多的冗余代码
- 许多的CSS其实是无用的,浪费了带宽
- 把样式文件切分到许多文件中,更加琐碎
方式二:有状态的主题
该方式可以实现基于条件选择不同的主题皮肤,并允许用户在客户端随时切换主题。非常适合需要客户端样式切换功能,或者需要对站点某一部分(区域)进行独立样式设置的场景。
具体实现
还是类似上一节中 Tab 的这个例子,我们可以将 Tab 部分的 (S)CSS 改为如下形式:
.tab {
background-color: gray;
.t-red & {
background-color: red;
}
.t-blue & {
background-color: blue;
}
}
这里我们把.t-red与.t-blue称为 Tab 元素的上下文环境(context)。Tab 元素会根据 context 的不同展示出不同的样式。
最后我们给body元素加上这个开关
<body class="t-red">
<ul class="tabs">...</ul>
</body>
此时 Tab 的颜色为红色。
当我们将t-red改为t-blue时,Tab 就变为了蓝色主题。
进一步的,我们可以创建一些 (S)CSS 的 util class(工具类)来专门控制一些 CSS 属性,帮助我们更好地控制主题。例如我们使用如下的.u-color-current类来控制不同主题下的字体颜色
.u-color-current {
.t-red & {
color: red;
}
.t-blue & {
color: blue;
}
}
这样,当我们在不同主题上下文环境下使用.u-color-current时,就可以控制元素展示出不同主题的字体颜色
<body class="t-red">
<h1 class="page-title u-color-current">...</h1>
</body>
上面这段代码会控制<h1>元素字体颜色为红色主题时的颜色。
优点
- 将许多主题放在了同一处代码中
- 非常适合主题切换的功能
- 非常适合站点局部的主题化
- 可以实现将主题应用于所有元素
缺点
- 有时有点也是缺点,将许多主题混杂在了同一块代码中
- 可能会存在冗余
方式三:配置主题
这种方式其实是在开发侧来实现主题样式的区分与切换的。基于不同的配置,配合一些开发的自动化工具,我们可以在开发时期根据配置文件,编译生成不同主题的 CSS 文件。
它一般会结合使用一些 CSS 预处理器,可以对不同的 UI 元素进行主题分离,并且向客户端直接提供主题样式下最终的 CSS。
具体实现
我们还是以 Sass 为例:
首先会有一份 Sass 的配置文件,例如settings.config.scss,在这份配置中定义当前的主题值以及一些其他变量
$theme: red;
然后对于一个 Tab 组件,我们这么来写它的 Sass 文件
.tab {
margin: 0;
padding: 0;
@if ($theme == red) {
background-color: red;
} @else {
background-color: gray;
}
}
这时,我们在其之前引入相应的配置文件后
@import "settings.config"; @import "components.tabs";
Tab 组件就会呈现出红色主题。
当然,我们也可以把我们的settings.config.scss做的更健壮与易扩展一些
$config: (
theme: red,
env: dev,
)
// 从$config中获取相应的配置变量
@function config($key) {
@return map-get($config, $key);
}
与之前相比,这时候使用起来只需要进行一些小的修改,将直接使用theme变量改为调用config方法
.tab {
margin: 0;
padding: 0;
@if (config(theme) == red) {
background-color: red;
} @else {
background-color: gray;
}
}
优点
- 访问网站时,只会传输所需的 CSS,节省带宽
- 将主题的控制位置放在了一个地方(例如上例中的
settings.config.scss文件) - 可以实现将主题应用于所有元素
缺点
- 在 Sass 中会有非常多逻辑代码
- 只支持有限数量的主题
- 主题相关的信息会遍布代码库中
- 添加一个新主题会非常费劲
方式四:主题调色板
这种方式有些类似于我们绘图时,预设了一个调色板(palette),然后使用的颜色都从其中取出一样。
在实现主题功能时,我们也会有一个类似的“调色板”,其中定义了主题所需要的各种属性值,之后再将这些信息注入到项目中。
当你经常需要为客户端提供完全的定制化主题,并且经常希望更新或添加主题时,这种模式会是一个不错的选择。
具体实现
在方式三中,我们在一个独立的配置文件中设置了一些“环境”变量,来标示当前所处的主题。而在方式四中,我们会更进一步,抽取出一个专门的 palette 文件,用于存放不同主题的变量信息。
例如,现在我们有一个settings.palette.red.scss文件
$color: red; $color-tabs-background: $color-red;
然后我们的components.tabs.scss文件内容如下
.tabs {
margin: 0;
padding: 0;
backgroung-color: $color-tabs-background;
}
这时候,我们只需要引入这两个文件即可
@import "settings.palette.red"; @import "components.tabs";
可以看到,components.tabs.scss中并没有关于主题的逻辑判断,我们只需要专注于编辑样式,剩下就是选择所需的主题调色板(palette)即可。
优点
- 编译出来的样式代码无冗余
- 非常适合做一些定制化主题,例如一个公司采购了你们的系统,你可以很方便实现一个该公司的主题
- 可以从一个文件中完全重制出你需要的主题样式
缺点
- 由于主要通过设定不同变量,所以代码确定后,能实现的修改范围会是有限的
方式五:用户定制化
这种模式一般会提供一个个性化配置与管理界面,让用户能自己定义页面的展示样式。
“用户定制化”在社交媒体产品、SaaS 平台或者是 Brandable Software 中最为常见。
具体实现
要实现定制化,可以结合方式二中提到的 util class。
首先,页面中支持自定义的元素会被预先添加 util class,例如 Tab 元素中的u-user-color-background
<ul class="tabs u-user-color-background">...</ul>
此时,u-user-color-background还并未定义任何样式。而当用户输入了一个背景色时,我们会创建一个``标签,并将 hex 值注入其中
<style id="my-custom">
.u-user-color-background {
background-color: #00ffff;
}
</style>
这时用户就得到了一个红色的 Tab。
优点
- 不需要开发人员的输入信息(是用户定义的)
- 允许用户拥有自己“独一无二”的站点
- 非常实用
缺点
- 不需要开发人员的输入信息也意味着你需要处理更多的“不可控”情况
- 会有许多的冗余
- 会浪费 CSS 的带宽
- 失去部分 CSS 的浏览器缓存能力


查看13道真题和解析