CSS 总结

Every browser understands that zero means no change.

CSS concepts

Layout

Position

通过 position 可以对正常的文档流产生影响。

child 用 absolute,parent 就需要 relative

使用 absolute 时,是相对于父级元素而言;对于 fixed ,则相对于视窗(viewport)

position 属性不是默认继承的,color 是;inherit 可以让 position 变得可继承

static 是默认情况,left/right/top/bottom/z-index 不起作用

relative 可以使得 z-index 起作用,根据 left/right/top/bottom 属性,将元素从默认位置推走

absolute 从正常文档流移除,left/right/top/bottom/z-index 起作用

fixed 像 absolute 同样从文档流中移除,但滚动页面并不移动元素,仅相对于整个页面变化位置

sticky ,先是 relative,直到滚动到 viewport 的指定位置,此时的行为更像 fixed

Legacy layout methods

传统方法,创造网格系统(Gird System)

通过百分比,设置流式布局(liquid layout)

  • 双栏布局
  • 传统网格框架

Semantic versus "unsemantic" grid systems 这一节不理解

使用 float 构建网格系统的限制:只能是一维

第三方网格系统:Bootstrap。

Support older browser

  • 考虑网站的可访问性
  • 网站不可能在所有浏览器上都一样
  • 对不同种类浏览器显示不同水平内容:1, 老旧浏览器不支持新特性,要确保能阅读文本;2, 浏览器支持新特性,则应用新特性
  • 创建可回退的 CSS:grid to float;方法:float、clear,display: inline-block,display: table,多栏布局,flex as a fallback for grid
  • feature queries: @supports (display: grid) 在 @supports 之外写旧浏览器能懂的代码,现代浏览器使用 @supports 内部的 CSS 代码。这里 feature queries 检查浏览器是否支持某特性,还有有些属性检查浏览器是否不支持某特性
  • flex 迭代的旧有版本
  • IE10, IE11 前缀版本的grid
  • 测试旧浏览器:跨浏览器测试;使用虚拟机

Responsive Design

https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design HTML 包含基础的响应式部分。例如,一段文字一开始位于大窗口,后来宽度变小,文字会被浏览器重新布局以适应。这叫「流体」布局。但是,当文字呈现在更窄的屏幕上时,文字呈现变得不自然。如果设定固定大小的布局,在多个屏幕上呈现会有水平滚动条,和很多被浪费掉的闲置空间。

除去「流式」布局,还有「固定宽度」构建页面方法。

在响应式设计之前的灵活布局,有根据分辨率判断布局的,等等。

「响应式设计」,由 Ethan Marcotte 第一次于 2010 年提出。有三点:

  1. 流体网格
  2. 流式图像
  3. media query

以下是在创建响应式站点时,可能用到的技术。

一、Media Queries

Media query 根据断点(breakpoints)切换布局。一个简单相反:为窄屏设计单列内容,为宽屏设计多列内容。

二、Flexible grids

响应式站点除去「断点」,还依赖灵活的网格。使用 float 设置。

三、Modern layout tech

多列、Flexbox、Grid 布局是默认响应式的。

四、Responsive images

img {
  max-width: 100%;
}

这种方法,可能导致图片过大超过视窗,进而浪费带宽。

五、Responsive typography 响应式排版

先对根元素 :root 也是 html,设置基本字体大小——单位可以是 px, %, em, rem。然后,对其他元素根据需要设计字体大小,单位是 rem,也就是相对于根元素。此外,还要通过 media query 调整不同屏幕大小上的同一元素大小。

另一种方法,是把字体单位改为 vw,1vw 等于当前视窗宽度的 1%。也就是,如果窗口宽度改变,对应的使用 vw 单位的元素也会发生改变。缺陷:无法放大/缩小。因此,不该单独使用 vw、vh。可这样用 calc(1.5rem + 3vw) 。最佳实践!

六、viewport meta tag

<meta name="viewport" content="width=device-width,initial-scale=1" />

这段代码,告诉移动端浏览器,应该将视窗宽度设置为设备宽度,显示文档的对移动端优化后的大小。

这段代码是必备的,在想要展示在移动端的情况下。

https://alistapart.com/article/responsive-web-design/

Unlike the web, which often feels like aiming for next week, architecture is a discipline very much defined by its permanence.

2010 年之后,网页出现在更多不同屏幕的设备上。

一、Meet media query

<link rel="stylesheet" type="text/css" href="*.css" media="screen" />
<link rel="stylesheet" type="text/css" href="*.css" media="print" />

这是最初的最直接的方法,后来 CSS 标准发展出以下写法:

<link rel="stylesheet" type="text/css" href="*.css" media="screen and (max-device-width: 480px)" />

而且,不仅在 <link> 标签中写,还可以在 CSS 样式文件中写。

@media screen and (max-device-width: 480px) {
  .column {
    float: none;
  }
}
/* OR */
@import url("*.css") screen and (max-device-width: 480px);

Media queries

https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Media_queries

@media media-type and (media-feature-rule) {
  /* CSS rules go here */
}

/* media-type 是可以省略的,如果省略,该样式默认适用于 screen, print */

而 meida-feature-rule 最常用于创建响应式的是宽度,高度更少见。有 max-width, min-width, width, max-height, min-height, height。width、height 几乎不用。

还有 orientation(portrait or landscape 纵向/横向);hover

一、逻辑

and、or、not 逻辑: and , , , not

二、选择断点

两种方式进行响应式设计:一种是从宽屏到窄屏,先以桌面端设计;一种是从窄屏到宽屏。后者被称为 mobile first。

三、viewport

<meta name="viewport" content="width=device-width, initial-scale=1" />

四、不必用 media query

Flexbox, Grid 和多栏布局自带响应式设计。

Text

text-indent

Color

RGB

primary, secondary, and tertiary colors on a color wheel

rgb(  0,   0,   0)
rgb(255, 255, 255)

rgb(255,   0,   0)
rgb(  0, 255,   0)
rgb(  0,   0, 255)

rgb(127,   0,   0)
rgb(  0, 127,   0)
rgb(  0,   0, 127)

rgb(255, 127,   0)
rgb(255,   0, 127)
rgb(127, 255,   0)
rgb(127,   0, 255)
rgb(  0, 255, 127)
rgb(  0, 127, 255)

Two colors that are opposite from each other on the color wheel are called complementary colors.

A very common way to apply color to an element with CSS is with hexadecimal or hex values. While hex values sound complicated, they're really just another form of RGB values.

HSL

The HSL color model, or hue, saturation, and lightness, is another way to represent colors.

The CSS hsl function accepts 3 values: a number from 0 to 360 for hue, a percentage from 0 to 100 for saturation, and a percentage from 0 to 100 for lightness.

blue hsl(240, 100%, 50%)

Transition/Gradient

linear-gradient

Opacity

opacity

Another way to set the opacity for an element is with the alpha channel. Like rgba(), hsla().

Border

border-left-width
border-left-style
border-left-color

border-left: width style color;

Shadow

box-shadow

values and units

  • vh, vw

Flexbox

一维布局。

  • flex-direction: row | row-reverse | column | column-reverse
  • flex-wrap: wrap | nowrap

Media Queries

参考资料

CSS 媒体查询是一种通过某些特征、特性和用户偏好来定位浏览器的方法,然后根据它们应用样式或者执行其他代码。也许世界上最常见的媒体查询是那些针对特定视窗范围然后应用自定义样式的查询,它孕育了响应式设计的整个理念。

/* 浏览器视窗宽度至少为 600px */
@media screen and (min-width: 600px) {
  .element {
    /* 应用的样式 */
  }
}

处理视窗宽度,还可以调整其他条件。比如屏幕分辨率、设备方向、操作系统偏好。

使用媒体查询

用在 HTML:

<html>
  <head>
    <!-- 用于全部用户 -->
    <link rel="stylesheet" href="all.css" media="all" />
    <!-- 用于屏幕至少 20em 宽 -->
    <link rel="stylesheet" href="small.css" media="(min-width: 20em)" />
    ...
    <!-- 还可以分几种宽度类型 -->
    ...
    <!-- 用于打印界面 -->
    <link rel="stylesheet" href="print.css" media="print" />
  </head>
  <!-- ... -->
</html

这种划分方式可用于微调网站性能,通过分割样式的方式按需下载样式文件。但要注意,这并不阻止不符合当前设备样式表的下载,只是把它们排在了低优先级。因此,如果在小尺寸屏幕上会下载对应的样式文件,如果在稍微大些的屏幕上,它会下载包括小界面的样式表(这种说法适应于上面的例子),因为它与这些查询中不止一个相匹配。

这只是 <link> 元素。媒体查询还可以用在与 <picture> 的 <source> 元素上,这样做能够告诉浏览器加载哪一个版本的图像。

<picture>
  <source srcset="cat-landscape.png" media="(min-width: 800px)">
  <source srcset="cat-cropped.png" media="(min-width: 600px)">

  <!-- 如果都不匹配,使用这一个 -->
  <img src="cat.png" alt="Cat photo">
</picture>

这样做能够让低配设备加载小图片,提升网站浏览体验。

竟然可以直接在 <style> 上用 media 属性。

<style>
  p {
    background-color: blue;
    color: white;
  }
</style>

<style media="all and (max-width: 500px)">
  p {
    background-color: yellow;
    color: blue;
  }
</style>

用在 CSS:

再次强调,CSS 是最常见的媒体查询应用场景。在样式表中,可以使用 @media 规则来包裹元素,并且在满足条件时应用一组样式来显示(或隐藏该元素)。可以根据实际情况设置浏览器匹配条件,比如屏幕宽度等。

/* 视窗宽度在 320px 与 480px 之间 */
@media only screen and (min-width: 320px) and (max-width: 480px) {
  .card {
    background: #bada55;
  }
}

也可以对 @import 导入的样式添加媒体查询,但这样做会增加网站渲染页面的时间。

这篇文章(CSS and Network Performance)介绍了一种方法:当你使用了 @import 却无法通过删除它提高性能时,可以在 <head> 加一个 <link>,这样浏览器就会提前下载对应 @import 的样式文件,直接跳过 @import 的部分,缩短网页渲染时间。

另一篇文章(Don't fight the browser preload scanner)介绍了浏览器预加载扫描器的作用,还有它是怎样帮助提高性能的。

用在 JavaScript:

当浏览器视窗宽度为 768px 时,输出 log。

// 创建媒体条件,指定视窗宽度最小 768px
const mediaQuery = window.matchMedia("( min-width: 768px )")

function handleTabletCHange(e) {
  // 如果媒体查询为真
  if (e.matches) {
    // 输出日志
    console.log("Media Query Matched!")
  }
}

// 注册事件监听
mediaQuery.addListener(handleTabletCHange)

// 初始化检查
handleTabletCHange(mediaQuery)

一篇文章(Working with JavaScript Media Queries)介绍了如何在 JavaScript 中操作媒体查询。旧做法:

function checkMediaQuery() {
  if (window.innerWidth > 768) {
    console.log("Media Query Matched!")
  }
}

window.addEventListener("resize", checkMediaQuery)

这样做只能匹配视窗方面的媒体查询。

媒体查询剖析

@media screen (min-width: 320px) and (max-width: 768px)
  • @media

它是定义媒体查询的关键词。

  • 媒体类型有 screen, print, all, speech
  • 媒体特征有 min-width, max-width

视窗/页面特征:width、height、aspect-ratio、orientation、overflow-block、overflow-inline。

显示质量:resolution、scan、grid、update、environment-blending、display-mode。

颜色:color、color-index、monochrome、color-gamut、dynamic-range、inverted-colors。

交互:pointer、hover、any-pointer、any-hover。

视频前缀:video-color-gamut、video-dynamic-range。

脚本:scripting。

用户偏好:prefers-reduced-motion、prefers-reduced-transparency、prefers-contrast、prefers-color-scheme、forced-colors、prefers-reduced-data。

  • 操作符:and、or/,、not

你真的需要媒体查询吗?

Ranald Mace 的通用设计理念:在最大程度上将产品设计成所有人都能使用,而不需要进行调整或专门设计。

Laura Kalbag 在 Accessibility for Everyone 中解释说,无障碍设计和通用设计之间的区别是微妙而重要的。一个无障碍设计师会创造一个大门,让坐轮椅的人进入,而一个通用设计师会创造一个任何人都能适应的入口,而不考虑他们的能力。

在网页上谈论通用设计是很困难的,几乎听起来像是空想,但是想一想,大约有 150 个不同的浏览器,大约有 50 种不同的用户偏好组合,正如我们之前提到的那样,仅安卓设备就有超过 24000 种不同的独特设备。

这意味着至少有 1800 万种可能的情况。用 Miriam Suzanne 的话说,“CSS试图在无限和未知的画布上进行未知内容的平面设计,跨越操作系统、界面和语言。我们中的任何人都不可能知道自己在做什么。”

这就是为什么假设真的很危险,因此当你设计、开发和考虑产品时,请不要假设,使用媒体查询确保你的内容能够正确显示在任何用户面前。

匹配数值范围

@media (min-width: 30em) and (max-width: 80em) {
  body {
    background-color: purple;
  }
}

@media (30em <= width <= 80em) {
  /* ... */
}

可以对媒体查询进行多层嵌套

@media (min-width: 20em), not all and (min-height: 40em) {  
  @media not all and (pointer: none) { ... }
  @media screen and ( (min-width: 50em) and (orientation: landscape) ), print and ( not (color) ) { ... }
}

可访问性

  • prefers-reduced-motion
@media screen and (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}
  • prefers-contrast
.button {
  background-color: #0958d8;
  color: #fff;
}

@media (prefers-contrast: high) {
  .button {
    background-color: #0a0db7;
  }
}
  • prefers-color-scheme
body {
  --bg-color: white; 
  --text-color: black;

  background-color: var(--bg-color);
  color: var(--text-color);
}

@media screen and (prefers-color-scheme: dark) {
  body {
    --bg-color: black;
    --text-color: white;
  }
}

7 Habits of Highly Effective Media Queries

  1. 内容决定断点,不要使用流行的断点
  2. 将布局视为一种改进
  3. 使用主要和次要中断点
  4. 使用相对单位
  5. 超越宽度
  6. 使用媒体查询进行条件加载
  7. 不要使用太多媒体加载

技巧

居中对齐

https://css-tricks.com/centering-css-complete-guide/

https://www.w3schools.com/csS/css_align.asp

一、水平居中

elem {
  margin-left: auto;
  margin-right: auto;
  width: 50%;
}

elem {
  margin: 0 auto;
  width: 50%;
}

/* inline, inline-* 元素 */
.text {
  text-align: center;
}

/* 块级元素 需要指定宽度,前2个也是块级元素居中样式 */
img {
  display: block;
  margin: 0 auto;
}
/* 多个块级元素排成一列横排 需要水平居中
main > div
.inline-block-center(main), .flex-center(main)
1. 设置好标准的 div 元素样式
*/
.inline-block-center {
  text-align: center;
  div {
    display: inline-block;
    text-align: left;
  }
}
.flex-center {
  display: flex;
  justify-content: center;
}
/* 多个块级元素排成一列竖排
main > div
*/
main div {
  margin: 5px auto;
}
/* 之后一定要指定每个 div 元素的宽度 */

二、垂直居中

/* inline, inline-*, 文本、链接等 */
  /* single line */
  .center-single-line-vertically {
    padding: 50px 0;
  }
  .center-single-line-vertically {
    height: 100px;
    line-height: 100px;
    white-space: nowrap;
  }
  /* multiple lines */
  .center-multiple-lines-vertically {
    padding: 50px 0;
  }
    /* 如果对多行设置 padding 无效,使用以下办法 */
  .center-multiple-lines-vertically {
    display: table;
    height: 350px; /* 大于文字高度*/
    p {
      display: table-cell;
      margin: 0;
      vertical-align: middle;
    }
  }
  .center-multiple-lines-vertically {
    display: flex;
    justify-center: center;
    flex-direction: column;
    height: 300px; /* 大于文字高度 */
  }
  .center-multiple-lines-vertically {
    position: relative;
    &::before {
      content: " ";
      display: inline-block;
      height: 100%;
      width: 1%;
      vertical-align: middle;
    }
    p {
      display: inline-block;
      vertical-align: middle;
    }
  }
/* 块级元素的垂直居中 */
  /* height 已知 */
  /* https://codepen.io/chriscoyier/pen/GRBVOj */
  .center-vertically {
    position: relative;
    .child {
      position: absolute;
      top: 50%;
      height: 100px;
      margin-top: -70px; /* box-sizing 非 border-box 的解决办法 */
    }
  }
  /* height 未知 */
  .center-vertically {
    position: relative;
    .child {
      position: absolute;
      top: 50%;
      transform: translateY(-50%);
    }
  }
  /* 元素高度拉伸到父元素 */
  .center-vertically {
    display: table;
    height: 300px;
    div {
      display: table-cell;
      vertical-align: middle;
    }
  }
  /* 与前文多行居中相同,使用 Flexbox */
  .center-vertically {
    display: flex;
    flex-direction: column;
    justify-content: center;
  }
    /* 或者这样写 */
    .center-vertically {
      display: flex;
      .child {
        margin: auto 0;
      }
    }

三、水平+垂直居中

.center {
  padding: 50px 0;
  text-align: center;
}
/* 元素宽高固定 */
.center {
  position: relative;
  .child {
    width: 300px;
    height: 100px;
    padding: 20px;

    position: absolute;
    top: 50%;
    left: 50%;

    margin: -70px 0 0 -170px; /* 这个缩进值是如何计算的 */
  }
}
/* 元素宽高未知 */
.center {
  height: 200px;
  width: 300px; /* 宽度要有 */
  position: relative;
  p {
    margin: 0;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}
/* Flexbox */
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}
/* Gird */
body, html {
  height: 100%;
  display: grid;
  .child {
    margin: auto;
  }
}

左右对齐

.right {
  position: absolute;
  right: 0;
}

.right {
  float: right;
}

.left {
  position: absolute;
  left: 0;
}

.left {
  float: left;
}

Clearing boxes wrapped around a float

https://www.w3schools.com/csS/css_align.asp

https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Floats#clearing_boxes_wrapped_around_a_float

当使用 float 时,有时内部图片会溢出到父元素之外,这时就需要一些 hack

居中 div

div {
  width: 80%;
  margin-left: auto;
  margin-right: auto;
}

两个元素分别位于左右两端

<p class="flavor">French Vanilla</p><p class="price">3.00</p>
p {
  display: inline-block;
}

.flavor {
  text-align: left;
  width: 50%;
}

.price {
  text-align: right;
  width: 50%;
}

如果 HTML 是这样的

<p>Caramel Macchiato</p>
<p>3.75</p>

第二个 p 元素,就会进入下一行。

选择2-6th子元素

#menu li:nth-child(n+2):nth-child(-n+6) {
  /* your styles go here */
}

消除水平滚动条

body {
  margin: 0;
}

html,body 对于 100% 的反应

html {
  height: 100%;
}

body {
  height: 100%;
}

在找到别人的解答时,我以为对 html body 进行设置 height 只需要其中一个,但结果却不是。为什么只有当 2 个都设置时,才会出现那样的样子呢?

https://codepen.io/tianheg/pen/yLRPZqo

斯坦福 CS142 课程相关图片 ◎ 斯坦福 CS142 课程相关图片

line-height 使用数值,不使用长度

/* Good */
elem {
  line-height: 1.1;
  font-size: 30px;
}

/* Bad */
elem2 {
  line-height: 1.1em;
  font-size: 15px;
}

两个元素的行高计算:1.1x30, 1.1x15。前者字体更大,行高更大。

区块居中

.block {
  margin: 0 auto;
}

position 进行相对定位

https://codepen.io/tianheg/pen/ExEvmXq

ul {
  position: absolute;
  top: 100px;
}

li {
  position: relative;
  left: 100px;
}

除第一项添加样式

https://codepen.io/tianheg/pen/wvYPLNy

li + li {
  background: pink;
}

简化的 CSS reset

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

Normalize.css 简单不少。 box-sizing 能让我使用盒子模型。

注意 :如果选择如下一个这般继承 box-sizing 的话,就不要在重置 CSS 中使用 box-sizing

继承 box-sizing

html {
  box-sizing: border-box;
}

*,
*::before,
*::after {
  box-sizing: inherit;
}

这使得改变插件或其他利用其他行为的组件的 box-sizing 变得更加容易。

使用 unset 而不是手动重置所有属性

像这样一个属性一个属性地重置是不必要的。

button {
  background: none;
  border: none;
  color: inherit;
  font: inherit;
  outline: none;
  padding: 0;
}

选中所有属性有个快捷方式: all 。把它设为 unset 就可以实现上述那么长达成的效果。

button {
  all: unset;
}

注意allunset 在 IE11 不受支持。

参考资料

Accessible image replacement

https://codepen.io/tianheg/pen/MWPrjJN

div {
  margin: 5rem;
}
// https://web.archive.org/web/20030805051841/http://moronicbajebus.com/playground/cssplay/image-replacement/
#one {
  border: 1px solid yellow;
  width: 100px;
  padding-top: 100px;
  height: 0;
  background: url(https://source.unsplash.com/random/100x100/?img=1) no-repeat;
}

#two {
  border: 1px solid yellow;
  text-indent: 100%;
  white-space: nowrap;
  overflow: hidden;
  background: url(https://picsum.photos/100/100) no-repeat;
}
// https://web.archive.org/web/20031002115428/http://www.mezzoblue.com/tests/revised-image-replacement/#gilderlevin
#three {
  width: 100px;
  height: 100px;
  position: relative;
}
#three span {
  background: url(https://picsum.photos/100/100) no-repeat;
  position: absolute;
  width: 100%;
  height: 100%;
}
#three-v2 {
  width: 100px;
  height: 100px;
  position: relative;
}
#three-v2 span {
  background: url(https://picsum.photos/100/100) no-repeat;
  position: absolute;
  width: 100%;
  height: 100%;
}

// https://nicolasgallagher.com/css-image-replacement-with-pseudo-elements/
#four {
  height: 100px; /* height of replacement image */
  padding: 0;
  margin: 0;
  overflow: hidden;
}

#four::before {
  content: url(https://picsum.photos/100/100);
  display: block;
}

/**
Old method(text-indent: -9000px):

.nir {
   height: 100px;
   padding: 0;
   margin: 0;
   overflow: hidden;
   text-indent: -9000px;
   background: url(image.gif) no-repeat 0 0;
}
*/

伪元素做 drop shadow

https://codepen.io/tianheg/pen/wvYpoaL

导航菜单点击失效

.nav-elem {
  pointer-events: none;
}

用 text-align: justify 分散排版

用 linear-gradient 作格線背景以及替代框線

CSS Animation Tricks

https://codepen.io/tianheg/pen/OJBZMgZ

不同浏览器对于在动画中的 z-index 的处理是不同的。

CSS Debug 技巧

* {
  outline: rgba(255, 0, 0, 0.25) solid 3px;
}

Shapes

矩形

https://codepen.io/tianheg/pen/yLRPmYr

#square {
  width: 100px;
  height: 100px;
  background: red;
}

#rectangle {
  width: 200px;
  height: 100px;
  background: red;
}

圆形

https://codepen.io/tianheg/pen/ExdbqyV

#circle {
  width: 100px;
  height: 100px;
  background: red;
  border-radius: 50%;
}

椭圆形

https://codepen.io/tianheg/pen/KKGyOME

#oval {
  width: 200px;
  height: 100px;
  background: red;
  border-radius: 100px / 50px;
}

三角形

https://codepen.io/tianheg/pen/NWOwQdE

#triangle-up {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
}

#triangle-down {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-top: 100px solid red;
}

#triangle-left {
  width: 0;
  height: 0;
  border-top: 50px solid transparent;
  border-right: 100px solid red;
  border-bottom: 50px solid transparent;
}

#triangle-right {
  width: 0;
  height: 0;
  border-top: 50px solid transparent;
  border-left: 100px solid red;
  border-bottom: 50px solid transparent;
}

#triangle-topleft {
  width: 0;
  height: 0;
  border-top: 100px solid red;
  border-right: 100px solid transparent;
}

#triangle-topright {
  width: 0;
  height: 0;
  border-top: 100px solid red;
  border-left: 100px solid transparent;
}

#triangle-bottomleft {
  width: 0;
  height: 0;
  border-bottom: 100px solid red;
  border-right: 100px solid transparent;
}

#triangle-bottomright {
  width: 0;
  height: 0;
  border-bottom: 100px solid red;
  border-left: 100px solid transparent;
}

梯形

https://codepen.io/tianheg/pen/jOeagmR

#trapezoid {
  border-bottom: 100px solid red;
  border-left: 25px solid transparent;
  border-right: 25px solid transparent;
  height: 0;
  width: 100px;
}

平行四边形

https://codepen.io/tianheg/pen/yLRpJoE

#parallelogram {
  width: 150px;
  height: 100px;
  transform: skew(20deg);
  background: red;
}

弧形尾箭头 Curved Tail Arrow

https://codepen.io/tianheg/pen/oNapLGN

#curvedarrow {
  position: relative;
  width: 0;
  height: 0;
  border-top: 9px solid transparent;
  border-right: 9px solid red;
  transform: rotate(10deg);
}
#curvedarrow::after {
  content: "";
  position: absolute;
  border: 0 solid transparent;
  border-top: 3px solid red;
  border-radius: 20px 0 0 0;
  top: -12px;
  left: -9px;
  width: 12px;
  height: 12px;
  transform: rotate(45deg);
}

六角星

https://codepen.io/tianheg/pen/wvYpWPe

#star-six {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid red;
  position: relative;
}
#star-six::after {
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-top: 100px solid red;
  position: absolute;
  content: "";
  top: 30px;
  left: -50px;
}

五角星

https://codepen.io/tianheg/pen/mdzpEpr

#star-five {
  margin: 50px 0;
  position: relative;
  display: block;
  color: red;
  width: 0px;
  height: 0px;
  border-right: 100px solid transparent;
  border-bottom: 70px solid red;
  border-left: 100px solid transparent;
  transform: rotate(35deg);
}
#star-five::before {
  border-bottom: 80px solid red;
  border-left: 30px solid transparent;
  border-right: 30px solid transparent;
  position: absolute;
  height: 0;
  width: 0;
  top: -45px;
  left: -65px;
  display: block;
  content: '';
  transform: rotate(-35deg);
}
#star-five::after {
  position: absolute;
  display: block;
  color: red;
  top: 3px;
  left: -105px;
  width: 0px;
  height: 0px;
  border-right: 100px solid transparent;
  border-bottom: 70px solid red;
  border-left: 100px solid transparent;
  transform: rotate(-70deg);
  content: '';
}

正五边形

https://codepen.io/tianheg/pen/zYmpBpb

#pentagon {
  position: relative;
  width: 54px;
  box-sizing: content-box;
  border-width: 50px 18px 0;
  border-style: solid;
  border-color: red transparent;
}
#pentagon::before {
  content: "";
  position: absolute;
  height: 0;
  width: 0;
  top: -85px;
  left: -18px;
  border-width: 0 45px 35px;
  border-style: solid;
  border-color: transparent transparent red;
}

正六边形

https://codepen.io/tianheg/pen/GRYyqQN

#hexagon {
  width: 100px;
  height: 57.735px;
  background: red;
  position: relative;
}
#hexagon::before {
  content: "";
  position: absolute;
  top: -28.8675px;
  left: 0;
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 28.8675px solid red;
}
#hexagon::after {
  content: "";
  position: absolute;
  bottom: -28.8675px;
  left: 0;
  width: 0;
  height: 0;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-top: 28.8675px solid red;
}

正八边形

https://codepen.io/tianheg/pen/ExdoyQJ

#octagon {
  width: 100px;
  height: 100px;
  background: red;
  position: relative;
}
#octagon::before {
  content: "";
  width: 42px;
  height: 0;
  position: absolute;
  top: 0;
  left: 0;
  border-right: 29px solid #eee;
  border-bottom: 29px solid red;
  border-left: 29px solid #eee;
}
#octagon::after {
  content: "";
  width: 42px;
  height: 0;
  position: absolute;
  bottom: 0;
  left: 0;
  border-top: 29px solid red;
  border-left: 29px solid #eee;
  border-right: 29px solid #eee;
}

心形

https://codepen.io/tianheg/pen/PoyEzam

#heart {
  position: relative;
  width: 100px;
  height: 90px;
}
#heart::before,
#heart::after {
  position: absolute;
  content: "";
  left: 50px;
  top: 0;
  width: 50px;
  height: 80px;
  background: red;
  border-radius: 50px 50px 0 0;
  transform: rotate(-45deg);
  transform-origin: 0 100%;
}
#heart::after {
  left: 0;
  transform: rotate(45deg);
  transform-origin: 100% 100%;
}

无穷大形

https://codepen.io/tianheg/pen/PoyEzBm

#infinity {
  position: relative;
  width: 212px;
  height: 100px;
  box-sizing: content-box;
}
#infinity::before,
#infinity::after {
  content: "";
  box-sizing: content-box;
  position: absolute;
  top: 0;
  left: 0;
  width: 60px;
  height: 60px;
  border: 20px solid red;
  border-radius: 50px 50px 0 50px;
  transform: rotate(-45deg);
}
#infinity::after {
  left: auto;
  right: 0;
  border-radius: 50px 50px 50px 0;
  transform: rotate(45deg);
}

菱形

https://codepen.io/tianheg/pen/qBJpNME

#diamond {
  width: 0;
  height: 0;
  border: 50px solid transparent;
  border-bottom-color: red;
  position: relative;
  top: -50px;
}
#diamond::after {
  content: '';
  position: absolute;
  left: -50px;
  top: 50px;
  width: 0;
  height: 0;
  border: 50px solid transparent;
  border-top-color: red;
}

钻石盾形

https://codepen.io/tianheg/pen/gOBoMdW

#diamond-shield {
  width: 0;
  height: 0;
  border: 50px solid transparent;
  border-bottom: 20px solid red;
  position: relative;
  top: -50px;
}
#diamond-shield::after {
  content: '';
  position: absolute;
  left: -50px;
  top: 20px;
  width: 0;
  height: 0;
  border: 50px solid transparent;
  border-top: 70px solid red;
}

Diamond Narrow Shape

https://codepen.io/tianheg/pen/ZEqvOMV

#diamond-narrow {
  width: 0;
  height: 0;
  border: 50px solid transparent;
  border-bottom: 70px solid red;
  position: relative;
  top: -50px;
}
#diamond-narrow::after {
  content: '';
  position: absolute;
  left: -50px;
  top: 70px;
  width: 0;
  height: 0;
  border: 50px solid transparent;
  border-top: 70px solid red;
}

Cut Diamond Shape

https://codepen.io/tianheg/pen/zYmpBJQ

#cut-diamond {
  border-style: solid;
  border-color: transparent transparent red transparent;
  border-width: 0 25px 25px 25px;
  height: 0;
  width: 50px;
  box-sizing: content-box;
  position: relative;
  margin: 20px 0 50px 0;
}
#cut-diamond::after {
  content: "";
  position: absolute;
  top: 25px;
  left: -25px;
  width: 0;
  height: 0;
  border-style: solid;
  border-color: red transparent transparent transparent;
  border-width: 70px 50px 0 50px;
}

鸡蛋形

https://codepen.io/tianheg/pen/oNapLaj

#egg {
  display: block;
  width: 126px;
  height: 180px;
  background-color: #f7e6ca;
  border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
}

吃豆人形状

https://codepen.io/tianheg/pen/KKGZMbx

#pacman {
  width: 0px;
  height: 0px;
  border-right: 60px solid transparent;
  border-top: 60px solid #ffd700;
  border-left: 60px solid #ffd700;
  border-bottom: 60px solid #ffd700;
  border-top-left-radius: 60px;
  border-top-right-radius: 60px;
  border-bottom-left-radius: 60px;
  border-bottom-right-radius: 60px;
}

对话气泡形

https://codepen.io/tianheg/pen/PoyEzVK

#talkbubble {
  width: 120px;
  height: 80px;
  background: red;
  position: relative;
  border-radius: 10px;
  left: 100px;
}
#talkbubble::before {
  content: "";
  position: absolute;
  right: 100%;
  top: 16px;
  width: 0;
  height: 0;
  border-top: 13px solid transparent;
  border-right: 26px solid red;
  border-bottom: 13px solid transparent;
}

RSS Feed

https://codepen.io/tianheg/pen/PoyEzLK

#rss {
  width: 20em;
  height: 20em;
  border-radius: 3em;
  background-color: #ff0000;
  font-size: 14px;
}
#rss::before {
  content: '';
  z-index: 1;
  display: block;
  height: 5em;
  width: 5em;
  background: #fff;
  border-radius: 50%;
  position: relative;
  top: 11.5em;
  left: 3.5em;
}
#rss::after {
  content: '';
  display: block;
  background: #ff0000;
  width: 13em;
  height: 13em;
  top: -2em;
  left: 3.8em;
  border-radius: 2.5em;
  position: relative;
  box-shadow:
    -2em 2em 0 0 #fff inset,
    -4em 4em 0 0 #ff0000 inset,
    -6em 6em 0 0 #fff inset
}

12 点爆发形状

https://codepen.io/tianheg/pen/MWPrexZ

#burst-12 {
  background: red;
  width: 80px;
  height: 80px;
  position: relative;
  text-align: center;
}
#burst-12::before,
#burst-12::after {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 80px;
  width: 80px;
  background: red;
}
#burst-12::before {
  transform: rotate(30deg);
}
#burst-12::after {
  transform: rotate(60deg);
}

8 点爆发形状

https://codepen.io/tianheg/pen/abREZxb

#burst-8 {
  background: red;
  width: 80px;
  height: 80px;
  position: relative;
  text-align: center;
  transform: rotate(20deg);
}
#burst-8::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  height: 80px;
  width: 80px;
  background: red;
  transform: rotate(135deg);
}

阴阳

https://codepen.io/tianheg/pen/GRYyqLE

#yin-yang {
  width: 96px;
  box-sizing: content-box;
  height: 48px;
  background: #eee;
  border-color: black;
  border-style: solid;
  border-width: 2px 2px 50px 2px;
  border-radius: 100%;
  position: relative;
}
#yin-yang::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 0;
  background: #eee;
  border: 18px solid black;
  border-radius: 100%;
  width: 12px;
  height: 12px;
  box-sizing: content-box;
}
#yin-yang::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background: black;
  border: 18px solid #eee;
  border-radius: 100%;
  width: 12px;
  height: 12px;
  box-sizing: content-box;
}

徽章丝带

https://codepen.io/tianheg/pen/zYmpBXg

#badge-ribbon {
  position: relative;
  background: red;
  height: 100px;
  width: 100px;
  border-radius: 50px;
}
#badge-ribbon::before,
#badge-ribbon::after {
  content: '';
  position: absolute;
  border-bottom: 70px solid red;
  border-left: 40px solid transparent;
  border-right: 40px solid transparent;
  top: 70px;
  left: -10px;
  transform: rotate(-140deg);
}
#badge-ribbon::after {
  left: auto;
  right: -10px;
  transform: rotate(140deg);
}

太空入侵者

https://codepen.io/tianheg/pen/VwEyjOK

#space-invader {
  box-shadow: 0 0 0 1em red,
    0 1em 0 1em red,
    -2.5em 1.5em 0 .5em red,
    2.5em 1.5em 0 .5em red,
    -3em -3em 0 0 red,
    3em -3em 0 0 red,
    -2em -2em 0 0 red,
    2em -2em 0 0 red,
    -3em -1em 0 0 red,
    -2em -1em 0 0 red,
    2em -1em 0 0 red,
    3em -1em 0 0 red,
    -4em 0 0 0 red,
    -3em 0 0 0 red,
    3em 0 0 0 red,
    4em 0 0 0 red,
    -5em 1em 0 0 red,
    -4em 1em 0 0 red,
    4em 1em 0 0 red,
    5em 1em 0 0 red,
    -5em 2em 0 0 red,
    5em 2em 0 0 red,
    -5em 3em 0 0 red,
    -3em 3em 0 0 red,
    3em 3em 0 0 red,
    5em 3em 0 0 red,
    -2em 4em 0 0 red,
    -1em 4em 0 0 red,
    1em 4em 0 0 red,
    2em 4em 0 0 red;
  background: red;
  width: 1em;
  height: 1em;
  overflow: hidden;
  margin: 50px 0 70px 65px;
}

电视

https://codepen.io/tianheg/pen/WNadxBy

#tv {
  position: relative;
  width: 200px;
  height: 150px;
  margin: 20px 0;
  background: red;
  border-radius: 50% / 10%;
  color: white;
  text-align: center;
  text-indent: .1em;
}
#tv::before {
  content: '';
  position: absolute;
  top: 10%;
  bottom: 10%;
  right: -5%;
  left: -5%;
  background: inherit;
  border-radius: 5% / 50%;
}

V形

https://codepen.io/tianheg/pen/XWxVKwL

#chevron {
  position: relative;
  text-align: center;
  padding: 12px;
  margin-bottom: 6px;
  height: 60px;
  width: 200px;
}
#chevron::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  width: 51%;
  background: red;
  transform: skew(0deg, 6deg);
}
#chevron::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  height: 100%;
  width: 50%;
  background: red;
  transform: skew(0deg, -6deg);
}

放大镜

https://codepen.io/tianheg/pen/PoyEzrJ

#magnifying-glass {
  font-size: 10em;
  display: inline-block;
  width: 0.4em;
  box-sizing: content-box;
  height: 0.4em;
  border: 0.1em solid red;
  position: relative;
  border-radius: 0.35em;
}
#magnifying-glass::before {
  content: "";
  display: inline-block;
  position: absolute;
  right: -0.25em;
  bottom: -0.1em;
  border-width: 0;
  background: red;
  width: 0.35em;
  height: 0.08em;
  transform: rotate(45deg);
}

Facebook logo

https://codepen.io/tianheg/pen/yLRpJdG

#facebook-icon {
  background: #4267b2;
  text-indent: -999em;
  width: 100px;
  height: 110px;
  box-sizing: content-box;
  border-radius: 5px;
  position: relative;
  overflow: hidden;
  border: 15px solid #4267b2;
  border-bottom: 0;
}
#facebook-icon::before {
  content: "/20";
  position: absolute;
  background: #4267b2;
  width: 40px;
  height: 90px;
  bottom: -30px;
  right: -37px;
  border: 20px solid #eee;
  border-radius: 25px;
  box-sizing: content-box;
}
#facebook-icon::after {
  content: "/20";
  position: absolute;
  width: 55px;
  top: 50px;
  height: 20px;
  background: #eee;
  right: 5px;
  box-sizing: content-box;
}

月牙

https://codepen.io/tianheg/pen/QWZaEeV

#moon {
  width: 80px;
  height: 80px;
  border-radius: 50%;
  box-shadow: 10px 15px #ffff99;
}

旗帜

https://codepen.io/tianheg/pen/qBJpaWb

#flag {
  width: 110px;
  height: 56px;
  box-sizing: content-box;
  padding-top: 15px;
  position: relative;
  background: red;
  color: white;
  font-size: 11px;
  letter-spacing: 0.2em;
  text-align: center;
  text-transform: uppercase;
}
#flag::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 0;
  border-bottom: 13px solid #eee;
  border-left: 55px solid transparent;
  border-right: 55px solid transparent;
}

扇形

https://codepen.io/tianheg/pen/zYmpKKG

#cone {
  width: 0;
  height: 0;
  border-left: 70px solid transparent;
  border-right: 70px solid transparent;
  border-top: 100px solid red;
  border-radius: 50%;
}

十字

https://codepen.io/tianheg/pen/oNapzzB

#cross {
  background: red;
  height: 100px;
  position: relative;
  width: 20px;
}
#cross::after {
  background: red;
  content: "";
  height: 20px;
  left: -40px;
  position: absolute;
  top: 40px;
  width: 100px;
}

房子:三角形+矩形

https://codepen.io/tianheg/pen/QWZaKKz

#base {
  background: red;
  display: inline-block;
  height: 55px;
  margin-left: 20px;
  margin-top: 55px;
  position: relative;
  width: 100px;
}
#base::before {
  border-bottom: 35px solid red;
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  content: "";
  height: 0;
  left: 0;
  position: absolute;
  top: -35px;
  width: 0;
}

有指向性的丝带

https://codepen.io/tianheg/pen/rNqpMWN

#pointer {
  width: 200px;
  height: 40px;
  position: relative;
  background: red;
}
#pointer::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 0;
  height: 0;
  border-left: 20px solid white;
  border-top: 20px solid transparent;
  border-bottom: 20px solid transparent;
}
#pointer::before {
  content: "";
  position: absolute;
  right: -20px;
  bottom: 0;
  width: 0;
  height: 0;
  border-left: 20px solid red;
  border-top: 20px solid transparent;
  border-bottom: 20px solid transparent;
}

锁形

https://codepen.io/tianheg/pen/qBJpaqa

#lock {
  font-size: 8px;
  position: relative;
  width: 18em;
  height: 13em;
  border-radius: 2em;
  top: 10em;
  box-sizing: border-box;
  border: 3.5em solid red;
  border-right-width: 7.5em;
  border-left-width: 7.5em;
  margin: 0 0 6rem 0;
}
#lock::before {
  content: "";
  box-sizing: border-box;
  position: absolute;
  border: 2.5em solid red;
  width: 14em;
  height: 12em;
  left: 50%;
  margin-left: -7em;
  top: -12em;
  border-top-left-radius: 7em;
  border-top-right-radius: 7em;
}
#lock::after {
  content: "";
  box-sizing: border-box;
  position: absolute;
  border: 1em solid red;
  width: 5em;
  height: 8em;
  border-radius: 2.5em;
  left: 50%;
  top: -1em;
  margin-left: -2.5em;
}

倒角

https://codepen.io/tianheg/pen/wvYpzox

#curved-corner-bottomleft,
#curved-corner-bottomright,
#curved-corner-topleft,
#curved-corner-topright {
  width: 100px;
  height: 100px;
  overflow: hidden;
  position: relative;
}
#curved-corner-bottomleft::before,
#curved-corner-bottomright::before,
#curved-corner-topleft::before,
#curved-corner-topright::before {
  content: "";
  display: block;
  width: 200%;
  height: 200%;
  position: absolute;
  border-radius: 50%;
}
#curved-corner-bottomleft::before {
  bottom: 0;
  left: 0;
  box-shadow: -50px 50px 0 0 red;
}
#curved-corner-bottomright::before {
  bottom: 0;
  right: 0;
  box-shadow: 50px 50px 0 0 red;
}
#curved-corner-topleft::before {
  top: 0;
  left: 0;
  box-shadow: -50px -50px 0 0 red;
}
#curved-corner-topright::before {
  top: 0;
  right: 0;
  box-shadow: 50px -50px 0 0 red;
}

参考资料

Libraries

Bootstrap

Bootstrap 是一个 CSS 框架。https://getbootstrap.com/

一、必要条件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap demo</title>
  </head>
  <body>
    <h1>Hello, world!</h1>
  </body>
</html>

全局 CSS 样式: box-sizing: border-box ,保证 padding 不干扰最终元素宽度计算。但有些时候,对于特定元素,需要设为 content-box

Reboot 提供类似 modern-normalize 的功能,重置浏览器默认样式,以此保证跨浏览器样式一致。

欢迎通过「邮件」或者点击「这里」告诉我你的想法
Welcome to tell me your thoughts via "email" or click "here"