重新领略前端CSS样式表的魅力

前言

虽然自己搞过web开发很长时间,但对最新的css技术和原理不甚了了,基本是粘贴复制。像helloworld.net这样清新的界面我就做不出来。于是想彻底学习一次样式表的主流技术。

基本概念

HTML自定义元素和标准元素

浏览器对待自定义元素,就像对待标准元素一样,只是没有默认的样式和行为。所有自定义元素都是HTMLUnknownElement对象的实例。

HTML5 标准规定了自定义元素是合法的。然后,W3C 就为自定义元素制定了一个单独的 Custom Elements 标准。它与其他三个标准放在一起---- HTML Imports,HTML Template、Shadow DOM----统称为 Web Components 规范。目前,这个规范只有 Chrome 浏览器支持。

也就是说,你可以定义一个自定义的元素,放在一个单独的html文件中,然后import它,以此达到复用的目的。

屏幕尺寸

指屏幕的对角线的长度,单位是英寸,1英寸=2.54厘米。
常见的屏幕尺寸有2.4、2.8、3.5、3.7、4.2、5.0、5.5、6.0等。

屏幕分辨率

指在横纵向上的像素点数,单位是px,1px=1个像素点。一般以纵向像素横向像素来表示一个手机的分辨率,如1960 x 1080。(这里的1像素指的是物理设备的1个像素点)。例如iphone6: 7501334。

屏幕像素密度/像素密度/屏幕密度

屏幕上每英寸可以显示的像素点的数量,单位是ppi,即“pixels per inch”的缩写。
屏幕像素密度与屏幕尺寸和屏幕分辨率有关。

注意点:设备像素和CSS像素不同,前者是物理像素,即每个像素,或者叫点,其大小是固定的;而CSS像素是相对的,实际物理尺寸是变化的,一个CSS像素可以包含多个设备像素。这个比值就是DPR(Device Pixel Ratio)值:

dpr值 = 设备上物理像素 (physical pixels) / 设备无关像素 (device-independent pixels (dips))

DPI值( Dots Per Inch) = 每英寸点数

PPI (Pixels Per Inch) = 每英寸像素数

“像素”只存在于电脑显示领域,而“点”只出现于打印或印刷领域。
对电脑显示屏,分辨率是用像素数目衡量;对数字文件印刷,分辨率是通常用每英寸所含点或像素〔dpi〕来衡量。

In digital image processing, pixels, dots, and points are all terms used to describe the smallest unit of an image. However, they have different meanings and applications:

  • Pixel: A pixel is the smallest unit of a digital image, and it stands for “picture element”. Pixels are the building blocks of digital images and are used to represent an image on a screen. Each pixel can have its own color and intensity value.
  • Dot: A dot refers to a single, isolated point on a display or image. Dots are used in printing and can be used to produce a fine-grained representation of an image or pattern.
  • Point: A point refers to a position on a screen or image. Points are used in computer graphics to describe a location in two-dimensional space. Points can be used to represent individual elements in an image or to describe the position of a line or curve.

视口和浏览器窗口

在普通的桌面端,视口的默认宽度和浏览器窗口的宽度一致。

viewport 通常是指用户网页的可视区域,简称”视区“。但是我们这里讨论的 viewport 不仅是这个概念。我们不妨把 viewport 分为 layout viewport、visual viewport 和 ideal viewport 三个概念。

在移动端,浏览器厂商面临着一个比较大的问题,他们如何将数以万计甚至可以说是数以亿计的pc端网页完整的呈现在移动端设备上,并且不会出现横向滚动条? 如果这个时候,视口的宽度还是和浏览器窗口的宽度一致?我们都知道pc端网页一般都为960px或者1024px,那么要完整的放下它们,我们移动端浏览器必须要有个容器放下它吧,而且只有有了这个容器我们才能很好的规定到底我移动端的浏览器到底能放下多大的页面吧(可能大于960 页可能大于1024)。这个数值最好大于960,而且设备间的这个容器大小是没有太大差异的。而且基于用户体验我们更关心width。

长度单位:px、em/rem和vh

  • px通常被称为绝对单位。em和rem为相对单位。默认的浏览器字体大小为16px。
  • 字体的大小如果采用em或rem,含义是相对对父级字体或根级字体(html)的大小。
    rem适配的本质是参照根元素字体,不管视图多大,在不同机型上,1rem等于视图的宽度,所以,根标签的font-size改成布局视口的大小。默认字体为16px,在tailwindcss里,w-1的宽度为0.25rem,也就是4px。
  • vh为视口高度(viewport height),1vh等于1%的当前视口高度。

相对单位有:em、rem、vh、vw、vmin、vmax 、%、calc()

auto的含义

我们可以在 margin, positioning, height, width 等等属性中使用 auto 这个值。
块级元素如

,

的 width 属性的初始值就是 auto, 意味着它们将占据其父元素的所有水平空间。
当一个元素的宽度被设置成 auto 时, 即使设置了 margin, padding, border 属性,也不会超出其父元素的水平空间。其内容框的宽度将是内容本身,减去 margin,padding 和 border。

对于 height 这个属性来说, 一个元素的高度等于它实际内容占用的高度,默认值就是 auto。
margin 属性来说, auto是将具有已知宽度的元素水平居中。
在 flex 布局的父元素内,给子元素的 margin 设置为 auto 会让这个子元素被 “推到” 对应的另一边,这在有些应用场景下是非常有用的。比如, 如果一个 flex 布局的元素设置成 margin-left: auto, 那么它就会被 “推到” 最右边。
在 flex 布局中,如果给一个子元素设置了 flex: auto, 就相当于设置了 flex: 1 1 auto。

百分比%的含义

  • width和height: 它们的百分比计算是基于包裹它的父元素的宽和高来计算
  • margin和padding: 百分比的计算是基于其包含块的宽度
  • border-radius的百分比参考值是自身的尺寸,于是你可以经常使用百分比来画出一个圆形来
  • font-size: 百分比参考值是它的父元素的font-size
  • line-height: 百分比参考的是自身的font-size大小

CSS属性的继承与覆盖

定义:父元素设置了某属性,子元素也会有该属性。属性设为“inherit”,就会继承父元素的样式。
样式的覆盖规则:

  • 根据引入方式确定优先级
    优先级由高到低依次为:“内联属性”——>“写在 style标签里”——>“外部链接”
  • 后写的覆盖先写的(同一级别)
    即就是在文件上代码行号更靠下的优先级更高
  • 加有“!important”的样式,优先级最高
    即无论哪一种情况,只要在样式上加了important,那么该样式的优先级最高。
  • 选择器优先级
    在选择器不同的情况下,给每种选择器制定一个权值,计算命中一个元素的所有选择器的总权值,值高者获胜。

CSS选择器

CSS组合选择符包括各种简单选择符的组合方式。在 CSS3 中包含了四种组合方式:

  • 后代选择器(以空格 分隔)
  • 子元素选择器(以大于 > 号分隔)
  • 相邻兄弟选择器(以加号 + 分隔)
  • 普通兄弟选择器(以波浪号 ~ 分隔)

通过两个API:document.querySelector() 和 document.querySelectorAll() 能定位到某个元素。

CSS 变量

声明一个自定义属性,属性名需要以两个减号(–)开始。

element {
  --main-bg-color: brown;
}
element {
  background-color: var(--main-bg-color);
}
:root {
  --main-bg-color: brown;
}

定义在根伪类 :root 下,就可以在 HTML 文档的任何地方访问到该变量。

CSS 布局基础

盒子模型

所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用。CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。
在这里插入图片描述

  • Margin(外边距) - 清除边框外的区域,外边距是透明的。
  • Border(边框) - 围绕在内边距和内容外的边框。
  • Padding(内边距) - 清除内容周围的区域,内边距是透明的。
  • Content(内容) - 盒子的内容,显示文本和图像。

注意:padding是对容器而言的,margin是对元素而言的,margin是距离容器、或同一容器内兄弟组件的边距。

绝对定位和相对定位

CSS position 属性可以是relative或absolute。元素的定位与文档流无关,所以它们可以覆盖页面上的其它元素
绝对定位的元素的位置相对于最近的已定位父元素,如果元素没有已定位的父元素,那么它的位置相对于。absolute 定位使元素的位置与文档流无关,因此不占据空间。absolute 定位的元素和其他元素重叠。
z-index属性指定了一个元素的堆叠顺序。

display属性

常见的值:block, inline,inline-block,table-cell, flex,grid。

描述
none此元素不会被显示。
block此元素将显示为块级元素,此元素前后会带有换行符。
inline默认。此元素会被显示为内联元素,元素前后没有换行符。
inline-block行内块元素。(CSS2.1 新增的值)
list-item此元素会作为列表显示。
run-in此元素会根据上下文作为块级元素或内联元素显示。
compactCSS 中有值 compact,不过由于缺乏广泛支持,已经从 CSS2.1 中删除。
markerCSS 中有值 marker,不过由于缺乏广泛支持,已经从 CSS2.1 中删除。
table此元素会作为块级表格来显示(类似 table,表格前后带有换行符。
inline-table此元素会作为内联表格来显示(类似 table),表格前后没有换行符。
table-row-group此元素会作为一个或多个行的分组来显示 ,类似 tbody
table-header-group此元素会作为一个或多个行的分组来显示(类似 thead
table-footer-group此元素会作为一个或多个行的分组来显示(类似 tfoot
table-row此元素会作为一个表格行显示(类似 tr
table-column-group此元素会作为一个或多个列的分组来显示(类似 colgroup
table-column此元素会作为一个单元格列显示(类似 col
table-cell此元素会作为一个表格单元格显示(类似 td 和 th
table-caption此元素会作为一个表格标题显示(类似 caption
inherit规定应该从父元素继承 display 属性的值

重点掌握flex和grid布局。采用flex布局能实现任意布局。

浮动

把一个元素“浮动”(float) 起来,会改变该元素本身和在正常布局流(normal flow)中跟随它的其他元素的行为。这一元素会浮动到左侧或右侧,并且从正常布局流 (normal flow) 中移除,这时候其他的周围内容就会在这个被设置浮动 (float) 的元素周围环绕。

float 属性有四个可能的值:

  • left — 将元素浮动到左侧。
  • right — 将元素浮动到右侧。
  • none — 默认值,不浮动。
  • inherit — 继承父元素的浮动属性。

正常布局流(normal flow)

是指在不对页面进行任何布局控制时,浏览器默认的 HTML 布局方式。

Flexbox 布局

采用flexbox布局,能解决之前需要**“浮动+负边距”**才能解决的布局问题。
父级display:flex之后,子元素会变成 “inline-flex”,表现为非块级元素, 不具有主动换行的特性,div 默认的块级元素特征会丢失。

子元素如何分配父容器的空间呢?根据子元素的三个属性值:flex-grow,flex-shrink 和 flex-basis。
当父容器有剩余空间时,会根据子元素的值按比例分配给各个子元素;当剩余空间为负值,即子元素的宽度和(或高度和)超过父容器的宽度或高度时,按照子元素设定的flex-shrink按比例缩小各个子元素。
flex-basis值代表了向父容器申请的宽度或高度的值,优先级高于width。

  • flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。
  • flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。flex-grow的值只接受一个整数。
  • 开发中最常见的写法是 flex:1,它表示 flex 项目扩展并填充可用空间。flex-grow会影响宽度或高度,具体取决于flex-direction属性。
flex布局示例

三行三列布局:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Three Rows and Three Columns</title>
 <style>
   .container {
     display: flex;
     flex-wrap: wrap;
   }

   .row {
     display: flex;
     flex-wrap: wrap;
     justify-content: space-between;
   }

   .col {
     flex: 1;
     padding: 10px;
   }
 </style>
</head>
<body>
 <div class="container">
   <div class="row">
     <div class="col">Column 1</div>
     <div class="col">Column 2</div>
     <div class="col">Column 3</div>
   </div>
   <div class="row">
     <div class="col">Column 4</div>
     <div class="col">Column 5</div>
     <div class="col">Column 6</div>
   </div>
   <div class="row">
     <div class="col">Column 7</div>
     <div class="col">Column 8</div>
     <div class="col">Column 9</div>
   </div>
 </div>
</body>
</html>

在这个例子中,我们创建了一个 container 容器,它使用 display: flex 和 flex-wrap: wrap 来设置为 flex 容器。然后,我们创建了三个 row 容器,每个 row 容器使用 display: flex 和 flex-wrap: wrap 来设置为 flex 容器。

接下来,我们为每个 col 容器设置 flex: 1,以便它们在主轴上平均分配空间。我们还为每个 col 容器添加了 padding: 10px,以便在水平和垂直方向上添加一些间距。

最后,我们将每个 col 容器添加到 row 容器中,并将所有容器添加到 container 容器中。这样,我们就创建了一个三行三列的布局。

水平和垂直居中

经常在一个容器中需要让文字和子元素保持水平和垂直居中,可以这样设置:

display: flex;
align-items: center;
justify-content: center;

text-align是设置或检索对象中文本的左中右对齐方式。
vertical-align是用于指定元素的上下垂直对齐方式。

Grid 布局

网格布局。

.mygrid {
      display: grid;
      gap: 0.8rem;
      grid-template-columns: repeat(4, minmax(0, 33.333%));
      margin: 1.5rem auto 3.75rem;
      padding: 0;
      width: 100%;
}

上面定义了包含四列的网格,每列等宽。

grid-template-columns: 100px 1fr 2fr 3fr;

这个定义了四列,后三列是相对宽度,比值为1:2:3。单位 fr 来定义网格轨道大小的弹性系数。每个定义了 的网格轨道会按比例分配剩余的可用空间。当外层用一个 minmax() 表示时,它将是一个自动最小值 (即 minmax(auto, ) ) .

定位技术

定位 (positioning) 能够让我们把一个元素从它原本在正常布局流 (normal flow) 中应该在的位置移动到另一个位置。
有五种主要的定位类型需要我们了解:

  • 静态定位(Static positioning)是每个元素默认的属性——它表示“将元素放在文档布局流的默认位置——没有什么特殊的地方”。
  • 相对定位(Relative positioning)允许我们相对于元素在正常的文档流中的位置移动它——包括将两个元素叠放在页面上。这对于微调和精准设计(design pinpointing)非常有用。
  • 绝对定位(Absolute positioning)将元素完全从页面的正常布局流(normal layout flow)中移出,类似将它单独放在一个图层中。我们可以将元素相对于页面的 元素边缘固定,或者相对于该元素的最近被定位祖先元素(nearest positioned ancestor element)。绝对定位在创建复杂布局效果时非常有用,例如通过标签显示和隐藏的内容面板或者通过按钮控制滑动到屏幕中的信息面板。
  • 固定定位(Fixed positioning)与绝对定位非常类似,但是它是将一个元素相对浏览器视口固定,而不是相对另外一个元素。这在创建类似在整个页面滚动过程中总是处于屏幕的某个位置的导航菜单时非常有用。
  • 粘性定位(Sticky positioning)是一种新的定位方式,它会让元素先保持和 position: static 一样的定位,当它的相对视口位置(offset from the viewport)达到某一个预设值时,它就会像 position: fixed 一样定位。

表格布局和多列布局

用得少了,不讲了。

滚动条问题

滚动条问题真烦恼。这里主要针对垂直滚动条的问题。
首先要确定body是否滚动,新闻内长文本一般会让body滚动,其它如后台管理界面一般不需要body滚动。
然后确定body内哪些div需要滚动。如果出现多个垂直滚动条,从外层到里层逐一分析每个div的高度,注意height:100%, height: calc(100vh-100px)技巧的使用。
此外,overflow的设置,一般auto比较合适,即鼠标移动上去出现滚动,移开就消失。

响应式设计

1.外部引入:

2. 内部引入: @media screen and (min-width:0px) and (max-width:400px){ //style样式 }

媒体查询例子

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>响应式布局</title>
    <style>
        /*基本样式*/
        body {
            margin: 0;
            padding: 0;
            background-color: #ddd;
        }
        .side {
            height: 300px;
            background-color: #4eb3b9;
        }
        .main {
            height: 300px;
            background-color: #ff0097;
        }
        /*device-width: >= 1000px*/
         @media screen and (min-width: 1000px) {
            .parent {
                width: 960px;
                margin: 0 auto;
            }
            .side {
                width: 300px;
                height: 300px;
                background-color: #4eb3b9;
                float: left;
            }
            .main {
                width: 650px;
                height: 300px;
                margin-left: 10px;
                background-color: #ff0097;
                float: left;
            }
         }
        /*device-width:400px-1000px*/
        @media screen and (min-width: 400px) and (max-width: 1000px) {
            .parent {
                display: flex;
            }
            .side {
                width: 300px;
            }
            .main {
                flex: 1;
                margin-left: 10px;
            }
        }
        /*device-width: <= 400px*/
        @media screen and (max-width: 400px) {
            .parent {
                display: flex;
                flex-flow: column wrap;
            }
            .side {
                flex: 1;
                margin-bottom: 10px;
            }
            .main {
                flex: 1;
            }
        }
    </style>
</head>
<body>
    <div class="parent">
        <div class="side"></div>
        <div class="main"></div>
    </div>
</body>
</html>

rem布局

所谓rem布局就是指为文档的根节点元素设置一个基准字体大小,然后所有的元素尺寸都以rem为单位来设定。

saas/scss和Less

Sass (Syntactically Awesome Stylesheets)是一种动态样式语言,Sass语法属于缩排语法,比css比多出好些功能(如变量、嵌套、运算,混入(Mixin)、继承、颜色处理,函数等),更容易阅读。

Sass的缩排语法,对于写惯css前端的web开发者来说很不直观,也不能将css代码加入到Sass里面,因此Sass语法进行了改良,Sass 3就变成了Scss(Sassy CSS)。SCSS(Sassy CSS)是CSS语法的扩展。这意味着每一个有效的CSS也是一个有效的SCSS语句,与原来的语法兼容,只是用{}取代了原来的缩进。

Less也是一种动态样式语言. 对CSS赋予了动态语言的特性,如变量,继承,运算, 函数. Less 既可以在客户端上运行 (支持IE 6+, Webkit, Firefox),也可在服务端运行 (借助 Node.js)。

主要差别:

  • Sass是在服务端处理的,而Less是需要引入less.js来处理Less代码输出CSS到浏览器,也可以在服务端处理。
  • 变量符不一样,Less是@,而Scss是$。
  • 输出设置,Less没有输出设置,Sass提供4中输出选项:nested, compact, compressed 和 expanded。
  • Sass支持条件语句,可以使用if{}else{},for{}循环等等。而Less不支持
  • scss可以采用@import引用的外部文件,如果不想编译时多生成同名的.css文件,命名必须以_开头, 文件名如果以下划线_开头的话,Sass会认为该文件是一个引用文件,不会将其编译为同名css文件。scss还可以用@use引入外部文件

Bootstrap

bootstrap为我们解决了什么?一致性的UI风格,简单易用的布局,实用的UI组件。

bootstrap 类样式中的 mt mb ml mr mx my pt pb pl pr px py 含义

内边距(pading)外边距(margin)

m - for classes 代表 margin

p - for classes 代表 padding

t - for classes that set margin-top or padding-top 设置margin-top或padding-top

b - for classes that set margin-bottom or padding-bottom 设置margin-bottom或padding-bottom

l - for classes that set margin-left or padding-left 设置margin-left或padding-left

r - for classes that set margin-right or padding-right 设置margin-right或padding-right

x - for classes that set both -left and -right 设置padding-left和padding-right或margin-left和margin-right

y - for classes that set both -top and -bottom 设置padding-top和padding-bottom或margin-top和margin-bottom

空白 – 在元素的所有4个边上设置边距或填充

0 – 将边距或填充设置为0

1 – 将边距或填充设置为.25rem(如果font-size为16px则为4px)

2 – 将边距或填充设置为.5rem(如果字体大小为16px则为8px)

3 – 将边距或填充设置为1rem(如果字体大小为16px,则为16px)

4 – 将边距或填充设置为1.5rem(如果字体大小为16px,则为24px)

5 – 将边距或填充设置为3rem(如果font-size为16px则为48px)

mt-3 设置上边距3rem

tailwind css

Windi CSS现在已经不再维护。目前主要是tailwind css和unocss。均采用约定成俗的组合式class记法帮我们定义样式。通过扫描HTML和CSS并按需生成实用程序,Windi CSS能够在开发中提供更快的加载时间和快速的HMR,并且不需要再生产中进行清除。
UnoCSS是一个具有高性能且极具灵活的即时原子化CSS引擎,具有按需加载的特性。原子化CSS是一种CSS的架构方式,它倾向于小巧且用途单一的class,并且会以视觉效果进行命名。

A utility-first CSS framework packed with classes like flex, pt-4, text-center and rotate-90 that can be composed to build any design, directly in your markup.

<figure class="md:flex bg-slate-100 rounded-xl p-8 md:p-0 dark:bg-slate-800">
  <img class="w-24 h-24 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto" src="/sarah-dayan.jpg" alt="" width="384" height="512">
  <div class="pt-6 md:p-8 text-center md:text-left space-y-4">
    <blockquote>
      <p class="text-lg font-medium">
        “Tailwind CSS is the only framework that I've seen scale
        on large teams. It’s easy to customize, adapts to any design,
        and the build size is tiny.”
      </p>
    </blockquote>
    <figcaption class="font-medium">
      <div class="text-sky-500 dark:text-sky-400">
        Sarah Dayan
      </div>
      <div class="text-slate-700 dark:text-slate-500">
        Staff Engineer, Algolia
      </div>
    </figcaption>
  </div>
</figure>

参考

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北极象

如果觉得对您有帮助,鼓励一下

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值