前端进阶高薪必看-CSS之手写篇

两栏布局的实现
一般两栏布局指的是左边一栏宽度固定,右边一栏宽度自适应,两栏布局的具体实现:

利用浮动,将左边元素宽度设置为 200px,并且设置向左浮动。将右边元素的 margin-left 设置为 200px,宽度设置为 auto(默认为 auto,撑满整个父元素)。

.outer {
height: 100px;
}
.left {
float: left;
width: 200px;
background: tomato;
}
.right {
margin-left: 200px;
width: auto;
background: gold;
}
复制代码
利用浮动,左侧元素设置固定大小,并左浮动,右侧元素设置 overflow: hidden; 这样右边就触发了 BFC,BFC 的区域不会与浮动元素发生重叠,所以两侧就不会发生重叠。

.left{
width: 100px;
height: 200px;
background: red;
float: left;
}
.right{
height: 300px;
background: blue;
overflow: hidden;
}
复制代码
利用 flex 布局,将左边元素设置为固定宽度 200px,将右边的元素设置为 flex:1。

.outer {
display: flex;
height: 100px;
}
.left {
width: 200px;
background: tomato;
}
.right {
flex: 1;
background: gold;
}
复制代码
利用绝对定位,将父级元素设置为相对定位。左边元素设置为 absolute 定位,并且宽度设置为 200px。将右边元素的 margin-left 的值设置为 200px。

.outer {
position: relative;
height: 100px;
}
.left {
position: absolute;
width: 200px;
height: 100px;
background: tomato;
}
.right {
margin-left: 200px;
background: gold;
}
复制代码
利用绝对定位,将父级元素设置为相对定位。左边元素宽度设置为 200px,右边元素设置为绝对定位,左边定位为 200px,其余方向定位为 0。

.outer {
position: relative;
height: 100px;
}
.left {
width: 200px;
background: tomato;
}
.right {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 200px;
background: gold;
}
复制代码
三栏布局的实现
三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:

利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的 margin 的值。

.outer {
position: relative;
height: 100px;
}

.left {
position: absolute;
width: 100px;
height: 100px;
background: tomato;
}

.right {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 100px;
background: gold;
}

.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
background: lightgreen;
}
复制代码
利用 flex 布局,左右两栏设置固定大小,中间一栏设置为 flex:1。

.outer {
display: flex;
height: 100px;
}

.left {
width: 100px;
background: tomato;
}

.right {
width: 100px;
background: gold;
}

.center {
flex: 1;
background: lightgreen;
}
复制代码
利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的 margin 值,注意这种方式,中间一栏必须放到最后:

.outer {
height: 100px;
}

.left {
float: left;
width: 100px;
height: 100px;
background: tomato;
}

.right {
float: right;
width: 200px;
height: 100px;
background: gold;
}

.center {
height: 100px;
margin-left: 100px;
margin-right: 200px;
background: lightgreen;
}
复制代码
圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。

.outer {
height: 100px;
padding-left: 100px;
padding-right: 200px;
}

.left {
position: relative;
left: -100px;

float: left;
margin-left: -100%;

width: 100px;
height: 100px;
background: tomato;
}

.right {
position: relative;
left: 200px;

float: right;
margin-left: -200px;

width: 200px;
height: 100px;
background: gold;
}

.center {
float: left;

width: 100%;
height: 100px;
background: lightgreen;
}
复制代码
双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。

.outer {
height: 100px;
}

.left {
float: left;
margin-left: -100%;

width: 100px;
height: 100px;
background: tomato;
}

.right {
float: left;
margin-left: -200px;

width: 200px;
height: 100px;
background: gold;
}

.wrapper {
float: left;

width: 100%;
height: 100px;
background: lightgreen;
}

.center {
margin-left: 100px;
margin-right: 200px;
height: 100px;
}
复制代码
水平垂直居中的实现
利用绝对定位,先将元素的左上角通过 top:50%和 left:50%定位到页面的中心,然后再通过 translate 来调整元素的中心点到页面的中心。该方法需要考虑浏览器兼容问题。

.parent {
position: relative;
}

.child {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
复制代码
利用绝对定位,设置四个方向的值都为 0,并将 margin 设置为 auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。该方法适用于盒子有宽高的情况:

.parent {
position: relative;
}
.child {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
}
复制代码
利用绝对定位,先将元素的左上角通过 top:50%和 left:50%定位到页面的中心,然后再通过 margin 负值来调整元素的中心点到页面的中心。该方法适用于盒子宽高已知的情况

.parent {
position: relative;
}

.child {
position: absolute;
top: 50%;
left: 50%;
margin-top: -50px; /* 自身 height 的一半 / margin-left: -50px; / 自身 width 的一半 */
}
复制代码
使用 flex 布局,通过 align-items:center 和 justify-content:center 设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中。该方法要考虑兼容的问题,该方法在移动端用的较多:

.parent {
display: flex;
justify-content:center;
align-items:center;
}
复制代码
另外,如果父元素设置了flex布局,只需要给子元素加上margin:auto;就可以实现垂直居中布局

.parent{
display:flex;
}
.child{
margin: auto;
}
复制代码
这里蛮有意思的 如果不在弹性布局中 margin:auto;只能做到水平居中

这其中的道理可以看这篇文章了解一下(具体就是与auto的定义有关)

实现一个三角形
CSS 绘制三角形主要用到的是 border 属性,也就是边框。

平时在给盒子设置边框时,往往都设置很窄,就可能误以为边框是由矩形组成的。实际上,border 属性是三角形组成的,下面看一个例子:

div {
width: 0;
height: 0;
border: 100px solid;
border-color: orange blue red green;
}
复制代码
将元素的长宽都设置为 0,显示出来的效果是这样的:

前端进阶高薪必看-CSS之手写篇

所以可以根据 border 这个特性来绘制三角形:

三角 1
div {
width: 0;
height: 0;
border-top: 50px solid red;
border-right: 50px solid transparent;
border-left: 50px solid transparent;
}
复制代码

三角 5
div {
width: 0;
height: 0;
border-top: 100px solid red;
border-right: 100px solid transparent;
}
复制代码

还有很多,就不一一实现了,总体的原则就是通过上下左右边框来控制三角形的方向,用边框的宽度比来控制三角形的角度。

实现一个扇形
用 CSS 实现扇形的思路和三角形基本一致,就是多了一个圆角的样式,实现一个 90° 的扇形:

div{
border: 100px solid transparent;
width: 0;
height: 0;
border-radius: 100px;
border-top-color: red;
}
复制代码

实现一个宽高自适应的正方形

  1. 利用 vw 来实现:
.square {
  width: 10%;
  height: 10vw;
  background: tomato;
}
复制代码
  1. 利用元素的 margin/padding 百分比是相对父元素 width 的性质来实现:
.square {
  width: 20%;
  height: 0;
  padding-top: 20%;
  background: orange;
}
复制代码
  1. 利用子元素的 margin-top 的值来实现:
.square {
  width: 30%;
  overflow: hidden;
  background: yellow;
}
.square::after {
  content: '';
  display: block;
  margin-top: 100%;
}
复制代码

画一条 0.5px 的线

采用 transform: scale()的方式,该方法用来定义元素的 2D 缩放转换:

transform: scale(0.5,0.5);
复制代码

采用 meta viewport 的方式

<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5"/>
复制代码

这样就能缩放到原来的 0.5 倍,如果是 1px 那么就会变成 0.5px。viewport 只针对于移动端,只在移动端上才能看到效果

设置小于 12px 的字体

在谷歌下 css 设置字体大小为 12px 及以下时,显示都是一样大小,都是默认 12px。

解决办法:

  • 使用 Webkit 的内核的-webkit-text-size-adjust 的私有 CSS 属性来解决,只要加了-webkit-text-size-adjust:none;字体大小就不受限制了。但是 chrome 更新到 27 版本之后就不可以用了。所以高版本 chrome 谷歌浏览器已经不再支持-webkit-text-size-adjust 样式,所以要使用时候慎用。
  • 使用 css3 的 transform 缩放属性-webkit-transform:scale(0.5); 注意-webkit-transform:scale(0.75);收缩的是整个元素的大小,这时候,如果是内联元素,必须要将内联元素转换成块元素,可以使用 display:block/inline-block/…;
  • 使用图片:如果是内容固定不变情况下,使用将小于 12px 文字内容切出做图片,这样不影响兼容也不影响美观。

如何解决 1px 问题?

1px 问题指的是:在一些 Retina屏幕 的机型上,移动端页面的 1px 会变得很粗,呈现出不止 1px 的效果。原因很简单——CSS 中的 1px 并不能和移动设备上的 1px 划等号。它们之间的比例关系有一个专门的属性来描述:

window.devicePixelRatio = 设备的物理像素 / CSS像素。
复制代码

打开 Chrome 浏览器,启动移动端调试模式,在控制台去输出这个 devicePixelRatio 的值。这里选中 iPhone6/7/8 这系列的机型,输出的结果就是 2:

这就意味着设置的 1px CSS 像素,在这个设备上实际会用 2 个物理像素单元来进行渲染,所以实际看到的一定会比 1px 粗一些。

解决1px问题的三种思路:

思路一:直接写 0.5px

如果之前 1px 的样式这样写:

border:1px solid #333
复制代码

可以先在 JS 中拿到 window.devicePixelRatio 的值,然后把这个值通过 JSX 或者模板语法给到 CSS 的 data 里,达到这样的效果(这里用 JSX 语法做示范):

<div id="container" data-device={{window.devicePixelRatio}}></div>
复制代码

然后就可以在 CSS 中用属性选择器来命中 devicePixelRatio 为某一值的情况,比如说这里尝试命中 devicePixelRatio 为 2 的情况:

#container[data-device="2"] {
  border:0.5px solid #333
}
复制代码

直接把 1px 改成 1/devicePixelRatio 后的值,这是目前为止最简单的一种方法。这种方法的缺陷在于兼容性不行,IOS 系统需要 8 及以上的版本,安卓系统则直接不兼容。

思路二:伪元素先放大后缩小

这个方法的可行性会更高,兼容性也更好。唯一的缺点是代码会变多。

思路是先放大、后缩小:在目标元素的后面追加一个 ::after 伪元素,让这个元素布局为 absolute 之后、整个伸展开铺在目标元素上,然后把它的宽和高都设置为目标元素的两倍,border 值设为 1px。接着借助 CSS 动画特效中的放缩能力,把整个伪元素缩小为原来的 50%。此时,伪元素的宽高刚好可以和原有的目标元素对齐,而 border 也缩小为了 1px 的二分之一,间接地实现了 0.5px 的效果。

代码如下:

#container[data-device="2"] {
  position: relative;
}
#container[data-device="2"]::after{
  position:absolute;
  top: 0;
  left: 0;
  width: 200%;
  height: 200%;
  content:"";
  transform: scale(0.5);
  transform-origin: left top;
  box-sizing: border-box;
  border: 1px solid #333;
}
复制代码

思路三:viewport 缩放来解决

这个思路就是对 meta 标签里几个关键属性下手:

<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
复制代码

这里针对像素比为 2 的页面,把整个页面缩放为了原来的 1/2 大小。这样,本来占用 2 个物理像素的 1px 样式,现在占用的就是标准的一个物理像素。根据像素比的不同,这个缩放比例可以被计算为不同的值,用 js 代码实现如下:

const scale = 1 / window.devicePixelRatio;
// 这里 metaEl 指的是 meta 标签对应的 Dom
metaEl.setAttribute('content', `width=device-width,user-scalable=no,initial-scale=${scale},maximum-scale=${scale},minimum-scale=${scale}`);
复制代码

这样解决了,但这样做的副作用也很大,整个页面被缩放了。这时 1px 已经被处理成物理像素大小,这样的大小在手机上显示边框很合适。但是,一些原本不需要被缩小的内容,比如文字、图片等,也被无差别缩小掉了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至22018681@qq.com 举报,一经查实,本站将立刻删除。

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
森林服务号的头像森林服务号
上一篇 2022年4月11日 上午8:59
下一篇 2022年4月11日 下午5:00

相关推荐

发表回复

登录后才能评论