# CSS

### 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

#### Flexbox
flexbox

学习路径：

1. [Flexbox](https://web.dev/learn/css/flexbox/)
2. [CSS Flexible Box Layout - CSS: Cascading Style Sheets | MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout)
3. [A Complete Guide to Flexbox | CSS-Tricks](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)
4. [What Happens When You Create A Flexbox Flex Container? --- Smashing Magazine](https://www.smashingmagazine.com/2018/08/flexbox-display-flex-container/)
5. [Everything You Need To Know About Alignment In Flexbox --- Smashing Magazine](https://www.smashingmagazine.com/2018/08/flexbox-alignment/)
6. [Flexbox: How Big Is That Flexible Box? --- Smashing Magazine](https://www.smashingmagazine.com/2018/09/flexbox-sizing-flexible-box/)
7. [Use Cases For Flexbox --- Smashing Magazine](https://www.smashingmagazine.com/2018/10/flexbox-use-cases/)
8. [Wes Bos Flexbox Resources](https://wesbos.com/flexbox-resources)

#### Grid
学习路径：

1. [Grid | WebDev](https://web.dev/learn/css/grid/)
2. [CSS Grid Layout - CSS: Cascading Style Sheets | MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout)
3. [A Complete Guide to Grid | CSS-Tricks](https://css-tricks.com/snippets/css/complete-guide-grid/)
4. [Understanding CSS Grid: Creating A Grid Container --- Smashing Magazine](https://www.smashingmagazine.com/2020/01/understanding-css-grid-container/)
5. [Grid by Example](https://gridbyexample.com/)

CSS Grid 是一个二维的页面布局系统，能够控制页面元素在行和列的排布。

Grid 布局特点：

1. A grid can be defined with rows and columns.
2. Direct children of the grid container will be automatically placed onto this grid.
3. Or, you can place the items in the precise location that you want.
4. Lines and areas on the grid can be named to make placement easier.
5. Spare space in the grid container can be distributed between the tracks.
6. Grid items can be aligned within their area.

Grid 术语：

- Grid lines: Grid 线有水平和垂直的两种，它们共同构成 grid 格子。
- Grid tracks: Grid 两条水平线/垂直线之间的格子区域就是 grid track。
- Grid cell: 一个 grid cell 就是 grid tracks 的最小单位。
- Grid area: 几个 grid cell 合成一个 grid area。
- Gaps: Tracks 之间的分隔区域是 gap。
- Grid container: 应用了 `display: grid` 的 HTML 元素，因此为直接子元素创建了一个新的网格格式上下文。
- Grid item: Grid 容器的直接子元素。

行和列：

```css
.container {
  display: grid;
  grid-template-columns: 5em 100px 30%;
  grid-template-rows: 200px auto;
  gap: 10px;
}
```

内部大小关键字：`min-content`, `max-content`, `fit-content()`

`fr` 单位只在 grid 布局中有效，描述 grid 容器中可用空间的共享。工作方式和 flexbox 中的 `flex: auto;` 相似。

#### Box Model
https://css-tricks.com/the-css-box-model/

Margin 并不影响盒子大小，但影响其他元素与盒子的交互。

盒子的大小计算方式：

Width = width + padding-left + padding-right + border-left + border-right
Height = height + padding-top + padding-bottom + border-top + border-bottom

如果不声明 padding，borders，它们可能为 0（使用了 CSS reset 规则），可能是浏览器默认值。

块级盒子的默认宽度：不写明宽度，盒子会有一个静态 / 相对位置，width 是 100%，padding 和 border 是 push inwards。但如果显示设置 width 是 100%，padding 则变为 push outward。

绝对定位盒子没有宽度时：宽度是内容的宽度，直到盒子宽度达到最近的父元素（相对位置）/浏览器窗口的宽度，然后开始换行。

浮动盒子没有宽度时：The box is only as wide as it needs to be to accommodate the content, up to as wide as its parent element.

行内元素也可以是盒子。

查看页面所有盒子：

```css
* {
  outline: 2px solid red !important;
}
```

#### Understanding Layout Algorithms
[Understanding Layout Algorithms](https://www.joshwcomeau.com/css/understanding-layout-algorithms/)

CSS 不仅仅是一系列属性的集合，它是一群相互连接的布局算法，每个算法都是一个复杂的系统，有着各自的规则和秘密机制。

布局算法包括：Flexbox、Positioned（例如 `position: absolute`）、Grid、Table、Flow（除去 flex、grid 以外的布局）。

```css
.box {
  z-index: 10;
}
```

以上 CSS 展示的是流式布局，但是 `z-index` 并不起作用，因为 `z-index` 要配合 `position` 才能使用。`z-index` 在流式布局算法中并无实现。

Flow 是非表格元素的默认布局算法。如果在流式布局中设置宽高，那么它所表示的就是元素的实际宽高；而在 Flex 布局中，宽高则是一种假设的尺寸。

识别布局算法：

```css
.help-widget {
  position: fixed;
  right: 0;
  bottom: 0;
}
.floated {
  float: left;
  margin-right: 32px;
}
```

冲突处理：当一个元素被应用多种布局时，优先级更高的布局生效。

行内魔法空格：在 Flow 布局中，图片和父元素之间出现空白，因为图片默认是 inline 元素。解决办法：
1. 将图片设置为 `display: block;`
2. 将图片设置为 `display: flex;`
3. 使用 `line-height: 0;`（不利于可访问性）

### 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：

```css
img {
  max-width: 100%;
}
```

五、Responsive typography 响应式排版：先对根元素设置基本字体大小，再对其他元素用 rem。或者使用 vw 单位，或 `calc(1.5rem + 3vw)`。

六、viewport meta tag：

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

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

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

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

media-feature-rule 最常用于创建响应式的是宽度。有 max-width, min-width, orientation(portrait or landscape), hover。

逻辑：`and`、`,`（or）、`not`

断点选择：两种方式——从宽屏到窄屏，或从窄屏到宽屏（mobile first）。

#### Container & Style Queries
https://una.im/style-queries/

Style Queries 允许查询同页面的父元素的样式。

Container queries 能够通过查询父选择器，得到它的大小和样式信息。让子元素有自己的内在响应逻辑。

Style Queries 能力：
1. 查询直接父级以将样式应用于子级
2. 给不可继承的属性添加样式
3. 选中特定父元素，为其子元素设置唯一样式（链式样式）
4. 通过更高优先级的变量，为样式分组
5. CSS 中的交互
6. 结合大小和样式查询

进一步了解：
- [MDN Docs on Container Queries](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries)
- [Next Gen CSS: @container](https://css-tricks.com/next-gen-css-container/)
- [Container Queries & the future of CSS](https://www.miriamsuzanne.com/speaking/responsive-components/)
- https://web.dev/patterns/layout/

### Decoration
#### Background
https://developer.mozilla.org/en-US/docs/Web/CSS/background

```css
background: linear-gradient(#223344);
background-attachment: ;
background-clip: ;
background-color: ;
background-image: ;
background-origin: ;
background-position: ;
background-repeat: ;
background-size: ;
```

对 html 和 body 设置 background 的区别：注意这两者之间的差异。

https://css-tricks.com/just-one-of-those-weird-things-about-css-background-on-body/

#### Font
https://www.cssfontstack.com/

```css
body {
  font: italic small-caps bold 50px/2 'Indie Flower', cursive;
}

/* Same as */
body {
  font-family: "Indie Flower", cursive;
  line-height: 2;
  font-weight: bold;
  font-style: italic;
  font-variant: small-caps;
  font-size: 50px;
}
```

https://developer.mozilla.org/en-US/docs/Web/CSS/font#syntax

#### Gradient
https://developer.mozilla.org/en-US/docs/Web/CSS/gradient/linear-gradient

The colors of the gradient are determined by two or more points: the starting point, the ending point, and, in between, optional color-stop points.

使用例子：

```css
linear-gradient(217deg, rgba(255,0,0,0.6), rgba(255,0,0,0) 66%),
linear-gradient(127deg, rgba(0,255,0,0.6), rgba(0,255,0,0) 66%),
linear-gradient(336deg, rgba(0,0,255,0.6), rgba(0,0,255,0) 66%)

linear-gradient(to left top, rgba(111,222,255,.6), rgba(222,111,255,.6))
linear-gradient(0deg, blue, green 40%, red)
linear-gradient(.25turn, red, 10%, blue)
```

注意：`linear-gradient()` 属于 `&lt;image&gt;` 类型，无法在 `background-color` 上使用，只能在 `background` 使用。

有趣例子：
- https://projects.verou.me/css3patterns/
- http://standardista.com/cssgradients/
- https://cssgradient.io/blog/css-gradient-examples/
- https://kittygiraudel.com/2013/02/04/dig-deep-into-css-gradients/
- https://whatamesh.vercel.app/ 生成动画渐变效果

#### Shadow
- box-shadow
- text-shadow

#### Shapes
Refers:
- [The Shapes of CSS | CSS-Tricks](https://css-tricks.com/the-shapes-of-css/)
- [CSS 奇技淫巧十八招](http://blog.kidwm.net/390)

各种 CSS 形状的代码示例：

矩形、圆形、椭圆形、三角形（上/下/左/右/左上/右上/左下/右下）、梯形、平行四边形、弧形尾箭头、六角星、五角星、正五边形、正六边形、正八边形、心形、无穷大形、菱形、钻石盾形、鸡蛋形、吃豆人、对话气泡、RSS Feed、12点爆发、8点爆发、阴阳、徽章丝带、太空入侵者、电视、V形、放大镜、Facebook logo、月牙、旗帜、扇形、十字、房子、有指向性的丝带、锁形、倒角。

详细 CSS 代码参见 https://css-tricks.com/the-shapes-of-css/

#### Transitions
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Transitions

```css
transition: <property> <duration> <timing-function> <delay>
transition-delay:
transition-duration:
transition-property:
transition-timing-function:
```

#### Image Rendering
```html
<img class="nes-avatar is-large" src="https://www.gravatar.com/avatar?s=15" alt="Gravatar image example" style="image-rendering: pixelated;">
```

没有 `?s=15` 就无法让 `image-rendering: pixelated;` 发挥作用。

#### Buttons
模板：

```css
button {
  background: ; /* normal color: #fff or linear-gradient() */
  text-decoration: ;
}
button:hover { }
```

透明背景按钮、插入实体动画按钮、点击动画按钮、插入背景图片的按钮、带有 icons 的按钮。

详细代码示例参见：https://codepen.io/tianheg/

按钮相关工具：
- https://www.cssportal.com/css3-button-generator/
- https://css3buttongenerator.com/index.html

参考资料：
1. [CSS Button Tutorial -- How to Styling HTML Buttons with CSS](https://www.freecodecamp.org/news/a-quick-guide-to-styling-buttons-using-css-f64d4f96337f/)

### Techniques
#### Centering
https://css-tricks.com/centering-css-complete-guide/
https://www.w3schools.com/csS/css_align.asp

水平居中：

```css
elem { margin: 0 auto; width: 50%; }
.text { text-align: center; }
img { display: block; margin: 0 auto; }
```

垂直居中（块级元素 height 未知）：

```css
.center-vertically {
  position: relative;
}
.center-vertically .child {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
}
```

Flexbox 垂直居中：

```css
.center-vertically {
  display: flex;
  flex-direction: column;
  justify-content: center;
}
```

水平 + 垂直居中（Flexbox）：

```css
.center {
  display: flex;
  justify-content: center;
  align-items: center;
}
```

Grid 居中：

```css
body, html {
  height: 100%;
  display: grid;
}
.child {
  margin: auto;
}
```

左右对齐：

```css
.right { float: right; }
.left { float: left; }
.right { position: absolute; right: 0; }
```

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。

#### CSS Page Height
https://www.freecodecamp.org/news/html-page-width-height/

Setting min-height to 100% on both html and body does not allow the body element to fill the page.

理想设置：

```css
html { height: 100%; }
body { min-height: 100%; }
```

现代做法：

```css
body { min-height: 100vh; }
```

高度和宽度都设置：

```css
html { background-color: #000; }
body { min-height: 100vh; max-width: 400px; background-color: papayawhip; margin: 0 auto; }
```

#### Hide Scrollbar
https://www.w3schools.com/howto/howto_css_hide_scrollbars.asp

```css
/* Hide scrollbar for Chrome, Safari and Opera */
.example::-webkit-scrollbar {
  display: none;
}

/* Hide scrollbar for IE, Edge and Firefox */
.example {
  -ms-overflow-style: none;  /* IE and Edge */
  scrollbar-width: none;  /* Firefox */
}
```

#### Hover on Touch Screen
触屏上的 CSS hover 问题。（Chrome Android）点击一下会选中可 hover 的文本。

```css
@media (pointer: fine) {
  /* 鼠标设备 */
  button:hover { color: #fff; }
}
@media (pointer: coarse) {
  /* 触屏设备 */
  button:hover { color: #ddd; }
}
```

参考：https://medium.com/time2hack/can-i-use-hover-on-touch-devices-d9f039e24899

#### Reduced Motion
https://css-tricks.com/introduction-reduced-motion-media-query/

- [Designing Safer Web Animation For Motion Sensitivity](http://alistapart.com/article/designing-safer-web-animation-for-motion-sensitivity/)

#### Text Underline Offset
https://stackoverflow.com/q/1734618/12539782

使用 `text-underline-offset` 增加文本和下划线之间的距离。

https://developer.mozilla.org/en-US/docs/Web/CSS/text-underline-offset

#### One Word Adjust
当鼠标悬浮在链接上时，只改变该链接的文本的字体大小，而不影响链接文本所在段落的行高。

Demo: https://github.com/tianheg/csszengarden/blob/main/days/first-30-days/3/index.html

#### CSS Skills & Tips
Refers:
1. [CSS 奇技淫巧十八招](http://blog.kidwm.net/390)
2. https://github.com/AllThingsSmitty/css-protips

区块居中：`.block { margin: 0 auto; }`

简化的 CSS reset：

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

继承 `box-sizing`：

```css
html { box-sizing: border-box; }
*, *::before, *::after { box-sizing: inherit; }
```

使用 `unset` 重置按钮：

```css
button { all: unset; }
```

注意：`all`、`unset` 在 IE11 不受支持。

#### Draw with CSS
用 CSS 画画。目标：画妹妹。

CSS 学习榜样：https://github.com/cyanharlow
作品：https://diana-adrianne.com/purecss-francine/

学习模仿 demo：https://codepen.io/tag/css-drawing

### Preprocessors
#### Sass
在 SASS 中定义属性选择器：

```text
.bg-brand-3 {
  background-color: black;
  &[type='button']:enabled {
    &:hover { background-color: orange; }
    &:active { background-color: green; }
  }
  &[type='submit'] {
    // css
  }
}
```

https://stackoverflow.com/a/69444953/12539782

### Resources
#### Learning CSS
如何学习 CSS？

系统教程：
- [MDN CSS](https://developer.mozilla.org/en-US/docs/Web/CSS)
- [web.dev Learn CSS](https://web.dev/learn/css/)
- [W3Schools CSS](https://www.w3schools.com/Css/)
- [CSS Tricks Guides](https://css-tricks.com/guides/)
- [Josh Comeau CSS Tutorials](https://www.joshwcomeau.com/tutorials/css/)
- [Grid for layout, Flexbox for components - Ahmad Shadeed](https://ishadeed.com/article/grid-layout-flexbox-components/)

更多资源：
- https://flexbox.io/
- https://cssgrid.io/
- https://www.csszengarden.com/
- https://learnxinyminutes.com/docs/css/
- https://www.quirksmode.org/
- https://css-irl.info/tags/css/
- https://24ways.org/
- https://css-tricks.com/snippets/

CSS 知识点列表：Animations, Backgrounds and borders, Box alignment, Box model, Columns, Conditional rules, CSSOM view, Flexbox, Flow layout, Fonts, Grid, Images, Lists and counters, Logical properties, Media queries, Positioning, Scroll snap, Shapes, Text, Transforms, Transitions。

CSS frameworks: [Pure](https://purecss.io/)

官方标准：
- [W3C Standards](https://www.w3.org/TR/)
- [CSS Working Group Editor Drafts](https://drafts.csswg.org/)

有用资料：
- [CSS Tricks](https://css-tricks.com/)
- [Una Kravets](https://una.im/)
- [Ahmad Shadeed](https://ishadeed.com/)
- https://www.gridtoflex.com/
- [Miriam's CSS Sandbox](https://css.oddbird.net/)

#### Web Dev Guide
https://web.dev/learn/css/

Box Model：盒子模型是 CSS 的核心。`display` 的值不同，盒子的状态不同。

自定义盒子大小（extrinsic sizing）vs 使用浏览器默认大小（intrinsic sizing）。

当内容太多，盒子无法放下时，使用 `overflow` 处理。

```css
box-sizing: border-box;
```

Selectors 选择器：通用选择器、属性选择器、伪类/伪元素（`::`）、Combinators（子代、相邻兄弟、后续兄弟、子组合器）。

Cascade 层叠算法四个阶段：
1. Position and order of appearance
2. Specificity
3. Origin
4. Importance

优先级：id > 类 > 标签。不建议通过 id 添加样式，很难覆盖。

CSS 来源优先级（从低到高）：User agent base styles < Local user styles < Authored CSS < `!important` < Local user styles `!important` < User agent `!important`

重要性：normal < animation < !important < transition

参考资料：
1. https://developer.mozilla.org/en-US/docs/Web/CSS
2. https://flukeout.github.io/
3. User agent stylesheets: [Chromium](https://chromium.googlesource.com/chromium/blink/+/master/Source/core/css/html.css), [Firefox](https://searchfox.org/mozilla-central/source/layout/style/res/html.css), [Webkit](https://trac.webkit.org/browser/trunk/Source/WebCore/css/html.css)
4. [Selectors Explained](https://kittygiraudel.github.io/selectors-explained/)
5. [The CSS Cascade](https://wattenberger.com/blog/css-cascade)

#### Practice
CSS Diner: https://flukeout.github.io/

CSS Speedrun: https://css-speedrun.netlify.app/

#### NES Style Framework
https://github.com/nostalgic-css/NES.css


相关：[[coding|coding]]

相关：[[create-beautiful-card|create-beautiful-card]]
