css 学习总结

264 阅读12分钟

盒模型

  • padding 不能为负值,而 margin 可以为负值
  • 背景色会平铺到非 margin 的区域
  • margin-top 传递的现象及解决方案
  • margin 上下叠加的现象及解决方案

块级盒子

  • 独占一行
  • 支持所有样式
  • 不写宽度的时候,根父容器的宽度相同
  • 所占区域是一个矩形

内联盒子

  • 盒子不会产生换行
  • 有些样式不支持,例如: width、height等
  • 不写宽度的时候,宽度由内容决定
  • 所占的区域不一定是矩形
  • 内联标签之间会有空隙

消除内联标签之间的间隙

.box{
  font-size: 0
}

不要使用 inline-block 来实现布局

  • inline-block 之间存在间隙;代码压缩可能导致生产和开发不一致
  • inline-block 默认基线对齐;图文混合导致对其不一致;
  • 行盒元素会绕开浮动元素环绕排列

自适应盒模型

父容器设置宽度,子容器不设置宽度,padding、margin等属性会向内收缩

标准盒模型

在标准模型中,如果你给盒设置 width 和 height ,实际设置的是 content box。padding 和 border 再加上设置的宽高一起决定整个盒子的大小

怪异盒模型

在怪异模型中,所有宽度都是可见宽度,所有内容宽度是该宽度减去border 和 padding

box-sizing 属性

content-box:width、height -> content

border-box:width、height -> content + padding + border

border-box 应用

  • 量取尺寸时不用再去计算一些值
  • 解决一些需要设置百分比和盒模型值

浮动

当元素被浮动时,会脱离文档流,根据 float 的值向左或向右移动,直到它的外边界碰到父元素的内边界或另一个浮动元素的外边界为止,是 CSS 布局中实现左右布局的一种方式

清除浮动

  • clear 属性
  • BFC
  • 空标签
  • .clearfix::after{}

特性

  • 只会影响后面的元素
  • 文本不会被浮动元素覆盖
  • 具备内联盒子特性:宽度由内容决定
  • 具备块级盒子特性:支持所有样式
  • 浮动放不下,会自动换行

BFC

概念

块级格式化上下文,是一个独立的渲染区域,让处于 BFC 内部的元素与外部的元素相互隔离,使内外元素的定位不会相互影响。

触发条件

  • overflow 值不为 visible、clip 的块元素;
  • 浮动元素 (float 值不为 none );
  • 绝对定位元素 ( position 值为 absolue 或 fixed );
  • display 值为 inline-block / table-cell / table-caption / flex / table-flex / grid /tab

应用场景

margin穿透

父元素高度塌陷

margin重叠

两栏自适应布局

<style>
.float-left {
  float: left;
}

.bfc-content {
  display: table-cell; width: 9999px;
  *display: inline-block; *width: auto;
}
</style>
  
<div class="flow-box">
    <img class="float-left" src="mm1.jpg" >
    <div class="bfc-content"><img src="mm1.jpg" width="100%" height="190"></div>
</div>

定位

相对定位

  • 相对定位的元素是在文档中的正常位置偏移给定的值
  • 不影响其他元素布局
  • 相对自身进行偏移

绝对定位

  • 绝对定位的元素脱离了文档流,绝对定位元素不占据空间
  • 具备内联盒子特性:宽度由内容决定
  • 具备块级盒子特性:支持所有样式
  • 绝对定位元素相对于最近的非 static 祖先元素定位。当这样的祖先元素不存在时,则相对于可视区定位

固定定位

  • 固定定位与绝对定位相似,但是会固定在可视区域中
  • 具备内联盒子特性:宽度由内容决定
  • 具备块级盒子特性:支持所有样式
  • 固定定位元素不受祖先元素影响

粘性定位

  • 粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位

z-index

Flex 布局

容器的属性

align-content

align-content 属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

当不折行的情况下,align-content 是不生效的

.box{
  display: flex;
  flex-wrap: wrap;
  /* 默认拉伸   */
  align-content: stretch;
}

项目属性

flex-shrink

flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

注意

一般都使用 class 定义样式,id 一般用于 js 快速的区别和获取元素 class,一般都用中横线分割,id 一般都使用驼峰命名法。

border-radius

动画

硬件加速

GPU 加速,擅长对 texture 进行偏移、放大缩小、旋转等,渲染时跳过 Layout,paint,只触发 Composite,速度极快

Layer 模型

CSS 属性为元素生成 Layer

Layer 会作为 texture 上传到 GPU

触发条件

3d 或 perspective transform 属性

使用 animation,transition 改变 opacity,transform 的元素

video、canvas、flash、CSS filters 等

requestAnimationFrame(callBack)

读写触发 layout

Time

animation、keyframes

Modules

scoped 方案

中小型项目

CSS Modules

vue3

<template>
  <div :class="$style.page">
    <!-- <div :class="$style.color">
      CSS Modules
    </div> -->

    <!-- <div :class="[$style.color,$style.box]">
      CSS Modules
    </div> -->

    <!-- <div :class="$style.header">
      <div :class="$style.header__item">BEM</div>
    </div> -->

    <div class="title">
      CSS Modules
    </div>
  </div>
</template>
<style lang="scss" module>
.page {
  font-size: 26px;
}

.color {
  color: red;
}

.box {
  padding: 20px;
  border: 1px solid red;
}

.header{
  &__item{
    font-size: 30px;
  }
}

:global(.title){
  font-size: red;
}
</style>

CSS in JS

模块化设计

设计原则

  • 可复用能继承要完整 —— 可复用、 有交互、有样式,有内容完整的功能、继承、覆盖样式
  • 周期性迭代 —— 项目开发中不断做设计做迭代

设计方法

  • 先整体后部分再颗粒化 —— 布局、页面、功能、业务
  • 先抽象再具体

实现落地

设计模式

oocss

原则一: 容器与内容分离

<!-- 容器与内容分离 -->
<div class="post">
  <p class="metadata">
    <a>Author name</a>commented on <a>21-02-2010</a>
  </p>
</div>

<!-- comment 中的 meta-data  -->
<div class="comment">
  <p class="metadata">
    <a>Author name</a>commented on <a>21-02-2010</a>
  </p>
</div>

<style>
  .post {}
  .comment {}
  .metadata {}
</style>

原则二:结构(基础对象)与皮肤分离

<div class="menu fix2"></div>
<style>
  .menu {
    color: green;
    font-size: 14px;
  }
  
  .fix2 {
    font-size: 16px;
  }
</style>

应用

Grid 栅格系统、布局组件等

BEM

作用:命名规范、让页面结构清晰

示例

// B 独立实体,本身就很有意义。
.opinions-box {
    margin: 0 0 8px 0;
    text-align: center;
  
    // E 块的一部分,没有独立含义,在语义上与其块相关联。
    &__view-more {
        text-decoration: underline;
    }

    &__text-input {
        border: 1px solid #ccc;
    }
  
    // M 块或元素上的标志。使用它们来更改外观或行为。
    &--is-inactive {
        color: gray;
    }
}

SMACSS

分类:Base、Layout、Modules、State、Theme

好处:易维护、易复用、易扩展...

命名规范:.l-header、.is-hidden、.theme-nav

ITCSS

分层:七层

Settings:变量

Tools:工具库,清除浮动之类

Generic:浏览器样式默认重置

Base:元素定制化的设置

Objects:OOCSS,通用组件

Components:通用组件

Trumps:权重最高的样式

ACSS

一个样式属性一个类

好处:极强的复用性、维护成本低

坏处:破坏了 CSS 命名的语义化

经典框架:tailwindcss

架构

架构:ITCSS +BEM +ACSS

分层:Settings、Tools、Base、ACSS、Theme、State

Elements 层:抽离公共元素样式

ACSS 层:抽离常用样式,例如圆角、多行隐藏之类,实现,可以用 sass 或者 tailwindcss

ElementUI

Ant Design

Bootstrap

TailWind

应用

局部渐变

.top {
  height: 1.96rem;
  background-size: 100% 1.59rem;
  background-image: linear-gradient(0deg, rgba(0,145,255,0) 4% #0091ff 50%);
  background-repeat: no-repeat;
}

自定义滚动条

/** 
 * 滚动条
 * 给特定的类加
 */
.g-ant-sider_main::-webkit-scrollbar {
  width : 6px;
  height: 6px;
} 

/* 滚动滑块 */
:-webkit-scrollbar-thumb {
  background: #51606d;
  border-radius: 3px;
}

/* 轨道 */
:-webkit-scrollbar-track { 
  background:#263849;
  border-radius: 3px;
}

文字选中样式

 ::selection {
   background-color: #b3d4fc;
   text-shadow: none;
 }

背景模糊

<div class="carousel">  
  <div class="carousel-item">  
    <img src="image1.jpg" alt="Image 1">  
  </div>  
  <div class="carousel-item">  
    <img src="image2.jpg" alt="Image 2">  
  </div>  
  <div class="carousel-item">  
    <img src="image3.jpg" alt="Image 3">  
  </div>  
</div>
.carousel {  
  position: relative;  
  overflow: hidden;  
  background-image: url('background.jpg'); /* 替换为你的背景图片URL */  
  background-size: cover;  
}  
  
.carousel::before {  
  content: "";  
  position: absolute;  
  top: 0;  
  right: 0;  
  bottom: 0;  
  left: 0;  
  background-image: inherit;  
  filter: blur(10px); /* 添加模糊效果 */  
  z-index: -1;  
}  

滑动轮播

<div class="box">
  <div class="box__item box__item--bg1">swiper1</div>
  <div class="box__item box__item--bg2">swiper2</div>
  <div class="box__item">swiper3</div>
</div>

<style>
.box {
  scroll-snap-type: x mandatory;
  overflow-x: auto;
  white-space: nowrap;

  &__item {
  display: inline-block;
  width: 100%;
  height: 100px;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  
    &--bg1 {
      background: pink;
    }

    &--bg2 {
      background: blue;
    }
  }
}
</style>

不定项居中 轮播图中的点

.box{
  display: flex;
  justify-content: center;
  align-items: flex-end;
  width: 300px;
  height: 150px;
  background: skyblue;
}

.box .item{
  width: 30px;
  height: 30px;
  background: pink;
  border-radius: 50%;
  margin: 5px;
}

视差滚动

<template>
  <div class="box">
    <img class="img1" />
    <img class="img3" />
  </div>
</template>
<style>
.box{
  perspective: 1px;
  padding: 0;
  height: calc(100vh);
  overflow: auto;
}
.img3{
  position: absolute;
  left: 30%;
  transform: translateZ(-1px) scale(4);
  width: 900px;
}

.img1{
  position: absolute;
  left: 60px;
  top: 30px;
}
</style>

SassMagic

vuecli vue3 下使用报警告

(235:3) autoprefixer: You should write display: flex by final spec instead of display: box

display: box 改为 display: flex即可

// _box-clamp.scss
@mixin ellipsis($lines: 1, $substract: 0) {
  @if $lines == 1 {
    white-space: nowrap;
    text-overflow: ellipsis;
    width: 100% - $substract;
    overflow: hidden;
  } @else {
    overflow: hidden;
    display: -webkit-flex; /* Safari */
    display: flex;
    // display: -webkit-box;
    // display: box;
    -webkit-line-clamp: $lines;
    line-clamp: $lines;
    -webkit-box-orient: vertical;
    box-orient: vertical;
  }
}

BEM

//SCSS
@include b(block) {
   background: red;
   @include e(header){
       font-size: 14px;

       @include m(css) {
           font-size: 18px;
       }
   };
}
//CSS
.block {
    background: red;
}
.block__header {
   font-size: 14px;
}
.block__header--css {
   font-size: 18px;
}

换肤

css 实现 修改变量实现

:root {
  --theme: #1890ff;
}
// 获取点击的背景色
var color = getComputedStyle(this).backgroundColor;
// 修改变量
document.documentElement.style.setProperty('--theme',color)

css 实现 属性选择器,html 更改属性来实现

// 默认亮色主题
:root {
  --text-color: #333;
  --bg1: #c7ffdd;
  --bg2: #fbd988;
}

html[data-theme='dark']{
  --text-color: #fff;
  --bg1: #102128;
  --bg2: #2d5567;
}

[data-theme='warn'] .box {
  background: yellow;
}

[data-theme='warn'] .text {
  color: yellow;
}

[data-theme='cool'] .box {
  background: blue;
}

[data-theme='cool'] .text {
  color: blue;
}
window.document.documentElement.setAttribute('data-theme', 'cool')

Sass 实现

// default.scss
$theme-default: (	
  box : (
    background: pink
  ),

  text : (
    color: pink
  ),

  home__item1 : (
    color: pink
  ),

  home__item3 : (
    color: pink
  )
)
// index.scss
@import "./default.scss";
@import "./cool.scss";
@import "./warm.scss";

// 映射 map 写法
$themes: (
  default: $theme-default,
  cool: $theme-cool,
  warm: $theme-warm
);

@mixin themable {
  // 循环属性值和属性名
  @each $section, $map in $themes {
    $map: $map !global;
    // & 表示使用的选择器 例如:.item等
    [data-theme="#{$section}"] & {
      // 占位符类似 vue slot
      @content;
    }
  }
}

@function themed($key, $color) {
  // 取出循环的变量
  @return map-get(map-get($map, $key), $color)
};

@mixin box {
  @include themable {
    background: themed('box', 'background');
  }
}

@mixin text{
  @include themable {
    color: themed('text', 'color');
  }
}

@mixin home__item1 {
  @include themable {
    color: themed('home__item1', 'color');
  }
}

@mixin home__item3 {
  @include themable {
    color: themed('home__item3', 'color');
  }
}

vue cli 可以通过 scss prependData 然后都可以使用 themed 、themable了

.item {
  @include themable {
    color: themed('home__item3', 'color');
  }
}

vue3 跟随系统切换

// useTheme
import { ref, watchEffect } from 'vue'
// 定义主题类型
type Theme = 'light' | 'dark' | 'OS'
// 本地存储 key
const LOCAL_KEY = '__theme__';
// 获取本地存储的主题 
const theme = ref<Theme>((localStorage.getItem(LOCAL_KEY) as Theme ) || 'light');
// 判断系统颜色是亮色还是暗色
const prefers = matchMedia('(prefers-color-scheme: dark)')
// 跟随系统
function followOS(){
  document.documentElement.dataset.theme = prefers.matches ? 'dark' : 'light' ;
}

watchEffect(()=>{
  localStorage.setItem(LOCAL_KEY,theme.value);
  if(theme.value === 'OS'){
    followOS()
    prefers.addEventListener('change' => followOS)
  } else {
    document.documentElement.dataset.theme = theme.value
    prefers.removeEventListener('change' => followOS)
  }
})

export default function useTheme(){
  return {
    theme
  }
}

window.matchMedia('(prefers-color-scheme: dark)').addListener(e => {
  if (e.matches) {
    // 应用暗色主题样式
    document.body.classList.add('dark-theme');
  } else {
    // 应用浅色主题样式
    document.body.classList.remove('dark-theme');
  }
});

国际化排版

阿拉伯国家从右向左进行阅读

逻辑属性

writing-mode 属性
从上到下阅读
<template>
  <div>hello world</div>
  <div>hello world</div>
</template>
<style lang="scss">
body{
  border: 1px solid black;
  block-size: 100px;
  writing-mode: vertical-lr;
}

div{
  border: 1px solid red;
  float: left;
  margin-inline-start: 30px;
}
</style>
从右向左
<template>
  <!-- dir 属性可以设置元素的显示方向,是从左往右,还是从右往左,
  当设置 auto 时会自动根据当前语言决定排列方向,dir 属性非常适合那些从右向左进行
  阅读的国家,例如:阿拉伯语,波斯语等
  -->
  <section dir="auto">
    <h2>اللغة العربية</h2>
    <div>اللغة العربية</div>
  </section>
</template>
<style lang="scss">
section{
  text-align: start;
}

h2{
  border-inline-start: .3em solid #ccc;
  padding-inline-start: .5em;
}
</style>

居中

transform

/* .box {
  position: relative;
  width: 300px;
  height: 200px;
  background: skyblue;
}

.box .item {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 200px;
  height: 50px;
  background: pink;
  transform: translate(-50%, -50%);
} */

.box {
  position: relative;
  display: flex;
  width: 300px;
  height: 200px;
  background: skyblue;
}

.box .item {
  width: 200px;
  height: 50px;
  background: pink;
  margin: auto;
}

子项分组布局

.main{
  display: flex;
  align-items: center;
}

.main .item:nth-of-type(3) {
  margin-right: auto;
}

.main .item:nth-of-type(6) {
  margin-right: auto;
}

等高布局

float 方案

不推荐,了解即可

.main {
  width: 500px
  overflow: hidden;
}

.main .item.left{
  float: left;
  /* 关键 */
  margin-bottom: -2000px;
  padding-bottom: 2000px;
}

.main .item.right{
  float: right;
}

两列与三列布局

flex 方案

.main{
  display: flex;
}

.col1{
  width: 200px;
}

/* 自适应 */
.col2{
  flex-grow: 1;
}

.col3{
  width: 200px;
}

float 方案

.main{
  
}

.col1{
  float: left;
  width: 200px;
}

/* 自适应 */
.col2{
  overflow: hidden;
}

侧边栏

<template>
  <div class="g-ant">
    <div class="g-ant__sider g-ant__sider--closed">
      <div class="g-ant-sider__wrap g-ant-sider__wrap--fixed">
        <div class="g-ant-sider__head"></div>
        <div class="g-ant-sider__main"></div>
        <div class="g-ant-sider__foot"></div>
      </div>
    </div>
    <div class="g-ant__main"></div>
  </div>
</template>
<style>
  .g-ant {
    display: flex;
  }

  .g-ant__sider {
    flex-shrink: 0;
    width: 208px;
    min-height: 100vh;
    background: #00152a;
  }

  .g-ant__main {
    flex-grow: 1;
    min-height: 100vh;
  }
  
  .g-ant-sider__wrap {
    display: flex;
    flex-direction: column;
    height: 100%;
    color: white;
  }

  .g-ant-sider__wrap--fixed {
    position: fixed;
    top: 0;
    left: 0;
    width: inherit;
    overflow: hidden;
  }

  .g-ant__sider--closed {
    width: 48px;
    overflow: hidden;
  }

  .g-ant-sider__head{
    flex-shrink: 0;
  }

  .g-ant-sider__main{
    flex-grow: 1;
  

  .g-ant-sider__foot{
    flex-shrink: 0;
  }
</style>

伪类选择器

:not

/* 当类名不具备 .hide 时才生效 */
.g-ant-main__head--fixed:not(.hide) + .g-ant-main__main{
  margin-top: 48px
}

/* 类名不是 `.fancy` 的 <p> 元素*/
p:not(.fancy) {
  color: green;
}

/* 非 <p> 元素 */
body :not(p) {
  text-decoration: underline;
}

/* 既不是 <div> 也不是 <span> 的元素 */
body :not(div):not(span) {
  font-weight: bold;
}

/* 不是 <div> 或 `.fancy` 的元素*/
body :not(div, .fancy) {
  text-decoration: overline underline;
}

/* <h2> 元素中不是有 `.foo` 类名的 <span> 元素 */
h2 :not(span.foo) {
  color: red;
}

文字渐变

/* 背景渐变 + 字体镂空 */
.text-gradient {
  background-image: linear-gradient(to bottom, #e5e4ea, #5ea8f2);
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

边角

边框的四个角 datav 中使用的是 svg 放大不失真,这里简单的可以使用 css

.panel{
  position: relative;
  
  &::before {
    position: absolute;
    top: 0;
    left: 0;
    content: '';
    width: 10px;
    height: 10px;
    border-left: 2px solid #02a6b5;
    border-top: 2px solid #02a6b5;
  }
}

相关资料

视频

默认样式清除

BFC

BEM

SMACSS

ITCSS

Scss 函数工具

散篇

CSS in JS

动画