---
title: css奇技淫巧
categories:
  - CS
status: doing
abbrlink: 20942
---

# grid 布局

> flex 布局操纵的是一维、一行/一列，grid 布局具备操纵二维的能力

设为网格布局以后，容器子元素（项目）的`float`、`display: inline-block`、`display: table-cell`、`vertical-align`和 `column-`等设置都将失效。

- grid-template-columns: 定义每一列的列宽
- grid-template-rows: 定义每一行的行高
- grid-row-gap: 行间距
- grid-column-gap: 列间距
- grid-gap: 行列间距合并
- grid-template-areas: 一个区域由单个或多个单元格组成
- grid-auto-flow: 默认值是 row，即"先行后列",即先填满第一行，再开始放入第二行
- justify-items: `单元格内容`的水平对齐
- align-items: `单元格内容`垂直对齐
- place-items: align-items 属性和 justify-items 属性的合并简写形式
- justify-content: `整个内容区域`水平对齐
- align-content: `整个内容区域`垂直对齐
- place-content: align-content 属性和 justify-content 属性的合并简写形式

> 设置的行或者列比较多的时候，可以使用 repeat()这个函数简化重复的值

## repeat()

第一个参数是重复的次数，第二个参数是所要重复的值、也可以是某个模式

```css
/* 重复 3个100px的列 */
grid-template-columns: repeat(3, 100px);
/* 重复这种布局2次 */
grid-template-columns: repeat(2, 100px 20px 80px);
/* 自动填充，直到容器放不下为止 */
grid-template-columns: repeat(auto-fill, 100px);
```

## fr

方便表示比例关系，网格布局提供了 fr 关键字

```css
grid-template-columns: 1fr 1fr;
```

## grid-template-areas

```css
grid-template-areas:
  "header header header"
  "main main sidebar"
  "footer footer footer";
```

## item 定位

![grid_1](/img/grid_1.png)

```css
/* 1号项目就是从第二根垂直网格线开始第四根结束 */
.item1 {
  grid-column-start: 2;
  grid-column-end: 4;
  background: red;
}
```

# 硬件加速(IE9+)

> 移动端开启,吃内存、增加耗电

`animation`、`transform`、`transition`不会自动开启`GPU`加速，利用`transform: translateZ(0)` 就可以开启`3D变换`，出发硬件加速

场景：`webKit内核`偶尔页面闪烁：`transform: translate3d(0, 0, 0);`

# 控制台打印 shield 徽章

```js
console.log(
  "%c" +
    eval("'mozzie.com'") +
    "%cv" +
    eval("'2.0.0'") +
    "%c\r\n" +
    eval("'了解更多:https://www.mozzie.com'"),
  "color: #fff; background: #5281FA; font-size: 12px;border-radius:2px 0 0 2px;padding:3px 6px;",
  "border-radius:0 2px 2px 0;padding:3px 6px;color:#333;background:#EBEBEB",
  "margin-top:10px;"
);
```

# css 判断 input 是否为空

`:placeholder-shown`：占位符是否显示的伪类，配合 `:not()` （不是必须，反过来也可以）

```html
<div id="demo">
  <input id="demo-input" type="text" placeholder="name" />
  <label id="demo-label">Name</label>
</div>
```

```css
#demo {
  width: 90%;
  max-width: 450px;
  position: relative;
}
#demo-input {
  width: 100%;
  height: 60px;
  line-height: 60px;
  font-size: 20px;
  border-bottom: 1px solid #ffa500;
}
#demo-input::placeholder {
  font-size: 0;
}
#demo-input:focus + label,
#demo-input:not(:placeholder-shown) + label {
  top: 0;
  font-size: 12px;
}
#demo-label {
  font-size: 22px;
  color: #ffa500;
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  transition: all 0.3s;
}
/*
* Default
*/
body {
  height: 100vh;
  display: flex;
}
body div {
  margin: auto;
}
body div input {
  border: 0;
  outline: 0;
}
```

# 居中

## transform 大法

```css
#wrapper {
  position: relative;
}
#box {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
```

## 0000 大法

```css
#wrapper {
  position: relative;
}
#box {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}
```

## 如何让 img 垂直居中

```html
<div id="imgWrapper">
  <img src="xxx.png" />
</div>
```

```css
.imgWrapper {
  display: table-cell;
  text-align: center;
  vertical-align: middle;
}
```

## ul 下 li 居中

```html
<!--外层包个div/section block元素 -->
<div>
  <ul class="clearfix">
    <li>1</li>
    <li>2</li>
  </ul>
</div>
```

```css
div{
  text-align: center
}
ul{
  display: inline-block
}
li{
  display: inline
  float: left
}
```

# js 随机渐变背景

```javascript
function getRandomRangeNum(min, max) {
  return min + Math.floor(Math.random() * (max - min));
}

function setRandomBg(el) {
  var left = getRandomRangeNum(0, 255);
  var bottom = getRandomRangeNum(0, 255);
  var css = [
    "linear-gradient(to left bottom,hsl(",
    left,
    ", 100%, 85%) 0%,hsl(",
    bottom,
    ", 100%, 85%) 100%)",
  ];
  el.style.background = css.join("");
}
```

# css 三角形

```css
span {
  width: 0;
  height: 0;
  border-top: 40px solid transparent;
  border-left: 40px solid transparent;
  border-right: 40px solid transparent;
  border-bottom: 40px solid #ff0000;
}
```

# 1px 神迹

## pc 端最优解

```html
<div style="height:1px;overflow:hidden;background:red"></div>
```

## 移动端 - 媒体查询 + transform

```css
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .border-bottom::after {
    -webkit-transform: scaleY(0.5);
    transform: scaleY(0.5);
  }
}
```

## 移动端 - 媒体查询 + 伪类

```css
.border__1px:before {
    content: '';
    position: absolute;
    top: 0;
    height: 1px;
    width: 100%
    background-color: #000;
    transform-origin: 50% 0%;
}
@media only screen and (-webkit-min-device-pixel-ratio:2) {
    .border__1px:before {
        transform: scaleY(0.5)
    }
}
@media only screen and (-webkit-min-device-pixel-ratio:3) {
    .border__1px:before {
        transform: scaleY(0.33)
    }
}
```

# 横竖屏适配

js 检测

```js
window.addEventListener("resize", () => {
  if (window.orientation === 180 || window.orientation === 0) {
    // 正常方向或屏幕旋转180度
    console.log("竖屏");
  }
  if (window.orientation === 90 || window.orientation === -90) {
    // 屏幕顺时钟旋转90度或屏幕逆时针旋转90度
    console.log("横屏");
  }
});
```

css 检测

```css
@media screen and (orientation: portrait) {
  /*竖屏...*/
}
@media screen and (orientation: landscape) {
  /*横屏...*/
}
```

# 像素

- 物理像素: 物理设备真实的像素
- 独立像素: 平时开发写的 px
- 设备像素比(DPR): = 物理像素 / 设备独立像素

```js
// 获取 DPR
window.devicePixelRatio;
```

也可以使用媒体查询

```css
@media (-webkit-min-device-pixel-ratio: 2), (min-device-pixel-ratio: 2) {
}
```

# srcset

使用 img 标签的 `srcset` 属性，浏览器会自动根据像素密度匹配最佳显示图片：

```html
<img src="conardLi_1x.png" srcset="conardLi_2x.png 2x, conardLi_3x.png 3x" />
```

# 字体小于 12px

css3 的 `transform` 属性，设置值为 `scale(x, y)` 定义 2D 缩放转换


# css 清浮动

```css
.clearfix::after {
  content: "";
  display: block;
  clear: both;
}
```

# ellipsis

## 单行

```css
.ellipsis {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
```

## 多行

```css
.ellipsis {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3; // 最多显示几行
  overflow: hidden;
}
```

# 页面导入样式时，使用 link 和 @import

> 你可能不信，ie5+就支持@import 了

- link: 与`dom`异步加载
- @import: 先加载`dom`


# em | rem 换算

相对于HTML根元素 `font-size` 来确定的，浏览器的默认字体高是 `16px`，因此:

- 16px = 1em
- 12px = .75em
- 10px = .625em

简化 rem 到 px 的换算，因为每个 rem 单位都是 10px 的倍数

```css
html {
  font-size: 62.5%; /* 这会将默认的 16px 缩小为 10px */
}
```

也可以使用 js 检测设置

```js
// set 1rem = viewWidth / 10
function setRemUnit() {
  var docEl = document.documentElement;
  var rem = docEl.clientWidth / 10;
  docEl.style.fontSize = rem + "px";
}

window.addEventListener("resize", setRemUnit);
window.addEventListener("pageShow", function (e) {
  if (e.persisted) setRemUnit()
});
```

# less 常用

## 变量

LESS 中的变量为完全的 `常量` ，所以只能定义一次

```less
@nice-blue: #5B83AD;
@light-blue: @nice-blue + #111;

#header {
  color: @light-blue;
}
```

输出

```less
#header {
  color: #6c94be;
}
```

## 混合

```less
.bordered {
  border-top: dotted 1px black;
  border-bottom: solid 2px black;
}
```

使用

```less
#menu a {
  color: #111;
  .bordered;
}
.post a {
  color: red;
  .bordered;
}
```

带参

```less
.border-radius (@radius) {
  border-radius: @radius;
  -moz-border-radius: @radius;
  -webkit-border-radius: @radius;
}
```

#header {
.border-radius(4px);
}

`@arguments`变量，包含了所有传递进来的参数. 如果你不想单独处理每一个参数

```less
.box-shadow (@x: 0, @y: 0, @blur: 1px, @color: #000) {
  box-shadow: @arguments;
  -moz-box-shadow: @arguments;
  -webkit-box-shadow: @arguments;
}
.box-shadow(2px, 5px);
```

无参

```less
.wrap () {
  text-wrap: wrap;
  white-space: pre-wrap;
  white-space: -moz-pre-wrap;
  word-wrap: break-word;
}

pre {
  .wrap;
}
```

## lighten 和 darken

```less
@color-base: #3bafda;
@color-hover:lighten (@color-primary,10%);
@color-focus:darken (@color-primary,10%);
```

## contrast

选择两种颜色中哪一种颜色与另一种颜色形成最大对比。

```less
p {
  a: contrast(#bbbbbb); //output: black
  b: contrast(#222222, #101010); //output: white
}
```

## JavaScript 表达式

```less
@var: ` "hello" .toUpperCase() + "!" `;
@height: `document.body.clientHeight`;
```

## & 父选择器

`&` 只能代表父元素，不能代表父亲的父辈元素，施加改性类或伪类

```less
a {
  color: blue;
  &:hover {
    color: green;
  }
}
```

## 重复父类名

```less
.button {
  &-ok {
    background-image: url("ok.png");
  }
  &-cancel {
    background-image: url("cancel.png");
  }

  &-custom {
    background-image: url("custom.png");
  }
}
```
