些情况下,我需要用一种简单的方法来创建网格布局。例如,每次我改变主意时,在不修改CSS的情况下快速画出五列网格。在本文中,我们一起探索一些用例,并思考如果实现及使用它们。
在深入探讨这些概念之前,首先我们来回顾一下 CSS 变量的基础知识, 我们也可以将它称为“自定义属性”。
所有主流浏览器都支持CSS变量,下面是各个浏览器的支持情况:
如果要定义CSS变量是全局变量,则需要将其添加到:root声明中(:root等效于<html>)。如果该变量特定于组件,则可以在该组内声明中定义它。
在下面的例子中,我定义了一个全局变量--size,它用于square 元素的宽度和高度。
:root {
--size: 50px;
}
.square {
width: var(--size);
height: var(--size);
}
如果--size没有定义,要怎么办呢?在传递的变量无效的情况下,CSS 支持定义默认变量或回退变量。
在下面的例子中的 var(--size, 10px)。如果--size无效,则宽度和高度值将为10px。
.square {
width: var(--size, 10px);
height: var(--size, 10px);
}
除此之外,还可以在内联CSS样式中使用CSS变量。例如
HTML
<div class="elem" style="--background: red;"></div>
CSS
.elem {
background: var(--background);
}
接着, 我们以上述这些概念,还演示一些事例。
在此设计中,我将CSS网格用于以下各项:
侧边栏的宽度是固定的,主内容是变化。假设侧边栏的宽度是240px。
1.边栏和主菜单
Html
<div class="o-grid" style="--columns: 240px 1fr">
<aside></aside>
<main></main>
</div>
Html
.o-grid {
display: grid;
grid-template-columns: var(--columns);
}
2. 表单项
按照设计,每行有两列,html 结构如下:
Html
<div class="o-grid" style="--columns: 1fr 1fr">
<div class="form-group"></div>
<div class="form-group"></div>
<div class="form-group"></div>
<div class="form-group"></div>
</div>
CSS
.o-grid {
display: grid;
grid-template-columns: var(--columns);
}
3. 三列布局
在下面的示例中,我添加了--repeat-number:3和--gap:8px作为内联CSS。这些变量将添加到o-grid类,网格的设置将基于这些变量。
HTML
<div class="o-grid" style="--repeat-number: 3; --gap: 8px;">
<div></div>
<div></div>
<div></div>
</div>
CSS
.o-grid {
display: grid;
grid-template-columns: repeat(var(--repeat-number), 1fr);
grid-gap: var(--gap, 0);
}
我喜欢在CSS变量中添加默认值,以防变量没有被设置。在上面的代码中,我使用了var(--gap, 0),如果使用者没有提供--gap变量,则其默认值将为0。
对我来说,这是一个广泛使用的用例,并且非常重要。我经常使用Grid minmax,但是当我在多个页面上使用它时,我遇到了一个问题。
让我们举一个不使用 CSS 变量的基本示例。
在 CSS 中,我使用minmax为每个网格项目定义最小宽度250px。
CSS
.o-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr);
grid-gap: 16px;
}
现在,如果设计要求网格项目的宽度至少为300px,应该怎么做?我需要创建类似以下版本吗?
.o-grid--2 {
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
}
想象一下,有五个不同的网格,每个网格具有不同的项目宽度,所以以上不是正确的解决方案。
使用CSS变量,我可以执行以下操作
.o-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(var(--item-width), 1fr);
grid-gap: var(--gap);
}
在HTML中,就可以在标签上设置 CSS 变量:
<!-- Example 1 -->
<div class="o-grid" style="--item-width: 250px;">
<div></div>
<div></div>
<div></div>
</div>
<!-- Example 2 -->
<div class="o-grid" style="--item-width: 350px;">
<div></div>
<div></div>
<div></div>
</div>
<!-- Example 3 -->
<div class="o-grid" style="--item-width: 150px;">
<div></div>
<div></div>
<div></div>
</div>
事例源码:https://codepen.io/shadeed/pen/7d3e0d575a5cecb86233fc7d72fa90d4
在示例中,有一个文章标题,其中包含作者姓名和标签。这些在页面中的排布方式是动态变化,所以需要一种快速切换这些布局方式的方法 。
HTML
<div class="article-header">
<h2>Article title</h2>
<div class="article-header__meta" style="--justify: space-between;">
<p>By Ahmad Shadeed</p>
<p>Published under: CSS, Design</p>
</div>
</div>
CSS
.article-header__meta {
display: flex;
justify-content: var(--justify);
}
有了它,我可以调整内联样式以将值更改为另一个关键字。我发现这在进行快速原型制作甚至是制作网站时很有用。
CSS 变量也适用于按钮元素。假设有一个带有两个input字段和一个按钮的表单。
我的目的是通过使用内联CSS变量来控制按钮的宽度。有时,按钮应占据其父控件的100%宽度。
html
<button class="c-button" style="--width: 100%;">Submit</button>
css
.c-button {
/* Other styles */
width: var(--width, initial);
}
另一个有用的用途是当有重影按钮(轮廓按钮)时。按钮的颜色可以是任何颜色,通过使用CSS变量,可以轻松更改颜色。
HTML
<button class="c-button c-button--ghost" style="--color: #5e35b1;">Save Edits</button>
<button class="c-button c-button--ghost" style="--color: #ec2828;">Delete</button>
CSS
.c-button--ghost {
/* Other styles */
background: transparent;
color: var(--color, #000);
border-color: currentColor;
}
CSS 变量同样适合悬停效果。悬停时,按钮背景将变为纯色,并且字体颜色为白色。
事例源码:https://codepen.io/shadeed/pen/f8e6969d5145d4dcd81aacf7a037c995
每个角色的大小都不同,这非常适合用 CSS 变量来解决。假设有四个不同大小的用户头像。
在CSS中,定义了以下样式:
.c-avatar {
display: inline-block;
margin-right: 2rem;
width: calc(var(--size, 1) * 30px);
height: calc(var(--size, 1) * 30px);
object-fit: cover;
border-radius: 50%;
box-shadow: 0 3px 10px 0 rgba(#000, 0.2);
}
通过使用Calc()函数,我可以传递一个--size 变量,它将乘以一个基本宽度值,在HTML中定义 --size变量:
<img src="user.jpg" alt="" class="c-avatar" style="--size: 1">
<img src="user.jpg" alt="" class="c-avatar" style="--size: 2">
<img src="user.jpg" alt="" class="c-avatar" style="--size: 3">
<img src="user.jpg" alt="" class="c-avatar" style="--size: 4">
事例源码:https://codepen.io/shadeed/pen/cdaac5ff667e1f7d9c8241655441f10d
人才们的 【三连】 就是小智不断分享的最大动力,如果本篇博客有任何错误和建议,欢迎人才们留言,最后,谢谢大家的观看。
作者:Ahmad shaded 译者:前端小智 来源:sitepoint
原文:https://css-tricks.com/patterns-for-practical-css-custom-properties-use/
家好,在本篇文章中,我们将深入了解JavaScript变量的方方面面。无论你是初学者还是有一定经验的开发者,本文都将为你揭开JavaScript变量的奥秘,让你轻松掌握这门重要的编程语言。
在JavaScript中,变量是存储数据的容器,它们允许你在程序中存储和操作各种类型的值。使用变量可以使你的代码更加灵活和可维护,因为你可以在程序中多次使用同一个值,而不需要重复输入。通俗的理解变量就是使用【特定符号】来代表【特定数据】。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>变量</title>
</head>
<body>
<script>
x = 1
y = 2
// x和y两个符号分别表示了数字1和2
//举例:使用变量记录数据
// 将用户输入的内容保存在 num 这个变量(容器)中
num = prompt('请输入一数字!')
// 通过 num 变量(容器)将用户输入的内容输出出来
alert(num)
document.write(num)
</script>
</body>
</html>
要使用变量,首先需要声明它。在JavaScript中,有三种声明变量的方式:使用var、let和const关键字。这些关键字的选择取决于变量的作用域和是否允许重新赋值。
关键字也叫保留字,是 JavaScript 中内置的一些英文词汇(单词或缩写),它们代表某些特定的含义。以下是JavaScript常见的一些关键字。
case else new var
catch export return void
class extends super while
const finally switch with
continue for this yield
debugger function throw
default if try
enum await implements protected
interface public package static
import from as
这些关键字在JavaScript的语法中有特定的用途,例如:
声明变量:关键字+变量名
赋值:变量名 = XX数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>变量声明和赋值</title>
</head>
<body>
<script>
// 声明(定义)变量有两部分构成:声明关键字、变量名(标识)
// let 即关键字,所谓关键字是系统提供的专门用来声明(定义)变量的词语
// age 即变量的名称,也叫标识符
let age
// 赋值,将 25 这个数据存入了 age 这个“容器”中
age = 25
// 这样 age 的值就成了 25
document.write(age)
// 也可以声明和赋值同时进行
let str = '你好,谧夜星球!'
alert(str);
</script>
</body>
</html>
作用域:
变量提升:
变量重复声明:
可变性:
全局对象属性:
初始化:
适用场景:
综上所述,let 和 const 是在现代 JavaScript 中更常见和推荐的变量声明方式,可以更好地控制作用域、避免一些潜在问题,并提高代码的可读性和可维护性。
在命名变量时,需要遵循一些规则:
变量的作用域指的是变量在代码中的可访问范围。JavaScript中有两种主要的作用域:全局作用域和局部作用域。
概念:使用 const 声明的变量称为“常量”。
使用场景:当某个变量永远不会改变的时候,就可以使用 const 来声明,而不是let。
命名规范:和变量一致
const PI = 3.14
注意: 常量不允许重新赋值,声明的时候必须赋值(初始化)
本文深入介绍了JavaScript变量的各个方面,从声明变量到变量的作用域、命名规则以及使用方法等。通过学习这些基础知识,你将能够更好地理解和运用JavaScript变量,为你的编程之路铺平道路。
希望本文能够帮助你更深入地理解JavaScript变量,让你在编程的旅程中游刃有余。如果你有任何关于JavaScript变量的疑问,欢迎在评论区提出,我将竭诚为你解答!
感谢阅读本文,希望能够对你有所帮助。记得点赞、分享!持续更新中!
自 IOS 13.0 支持深色模式 (DarkMode) 后,多主题逐渐流行起来,用户可以手动或自动切换到自己喜欢的主题色,本篇文章详细介绍下前端页面如何实现多主题适配。
Mac 系统支持的浅色和深色主题示意图:
在具体实施多主题方案之前,首先要了解两个问题
⭐️ 为什么会出现深色模式?
⭐️ 我应该去实施深色主题的适配吗?
相关研究调查数据显示,超过 80% (在 Mac 上,而不是在 iOS 上,但这给出了一个趋势),尽管这个数字可能被高估了,但这意味着有很大比例的人在使用它。所以对于使用深色模式的用户来说,切换到不支持的应用真的很不爽,他们很可能会为此删除掉应用或关掉页面。
多主题成为用户体验提升基本手段,现在化前端都应该支持此场景,接下来会深入讲解多主题在 WEB 场景中如何适配。
浏览器基于操作系统支持浅色深色两种风格,但是前端页面的多主题需要开发者具体开发才可以实现主题切换。
做具体实现之前,了解下系统层次支持暗黑模式的支持情况:
在现代化设备中,系统层都支持了深色和浅色主题,所以无论是新项目还是已经跑了多年的老项目都应该去做这件事。
页面基本是由自定义样式 + UI库来呈现整体视觉。 先从自定义样式说起:自定义样式使用CSS变量控制多主题(CSS变量基本使用在此不再过多赘述,入门请参考阮一峰老师写的CSS 变量教程)
<!-- html 节点添加主题自定义属性 -->
<html data-theme="light">
<!-- 使用CSS变量控制样式 -->
<body style="background: var(--body-background)"></body>
</html>
// 跟主题无关的变量放到root里
:root {
--border-radius-base: 6px;
}
// 跟主题相关变量,通过属性选择器提升优先级
html[data-theme='default']:root {
--body-background: #efefef;
}
html[data-theme='dark']:root {
--body-background: #000;
}
开源社区提供的UI库主题适配方案比较流行的就是通过CSS变量,但是由于CSS变量形成规范较晚,所以较老的项目是不支持的。Vue 的 Element UI 和 React 的 Ant Design 是社区发展较好的两个 UI 库,因为项目较老的原因都不支持CSS变量主题方案。
拿Ant Design来说,内部实现多主题是通过定义 less 变量,这样的做法是无法动态切换主题(下面会具体讨论动态切换主题)
Ant Design 目前正在着手将所有组件支持CSS变量,详细进展可以参考这里。
但是我们不能等官方支持后在着手做适配工作,需求不等人,以 antd 为例,适配浅色和深色主题目前可以通过分别构建不同主题样式,通过添加属性选择器前缀来控制antd样式的优先级,以达到适配主题的目的。
<html data-theme="light"></html>
html[data-theme='light'] .ant-button {color: #fff}
html[data-theme='dark'] .ant-button {color: #000}
页面切换主题具体需要从下面三个维度来考虑:
切换主题的核心思路是通过控制CSS变量,在不同主题下显示不同的样式。
⭐️ 系统主题切换
浏览器暴露主题切换接口:
CSS | 媒体查询 @media(prefers-color-scheme: dark) |
JavaScript | window.matchMedia("(prefers-color-scheme: dark)") |
api支持程度:
⭐️⭐️ 通过CSS媒体查询控制CSS变量:
body {
background: var(--body-background);
transition: background 0.3s;
}
@media (prefers-color-scheme: light) {
:root {
--body-background: #efefef;
--text-color: #333;
}
}
@media (prefers-color-scheme: dark) {
:root {
--body-background: #000;
--text-color: #ededed;
}
}
优点是实现简单,识别交给浏览器去做,简单页面直接使用这个方案即可。
缺点是不利于扩展,后续支持用户主动切换主题比较乏力,所以我们下面按照属性选择器加CSS变量实现控制。
⭐️⭐️ 通过JS暴露接口:
通过JS识别当前系统主题,对于CSS变量的控制不应该使用JS去写,因为当主题色多的话,需要对每个属性都执行这行代码:
document.documentElement.style.setProperty('--theme-color', '#YOURCOLOR');
JS控制CSS变量不利于后续扩展。
较合适的方案是上面提到的:通过属性选择器控制根节点CSS变量
/* 浅色模式 */
html[data-theme="light"]:root {
--body-background: #efefef;
--text-color: #333;
}
/* 深色模式 */
html[data-theme="dark"]:root {
--body-background: #000;
--text-color: #ededed;
}
JS通过识别系统主题,设置页面主题标识
// 给HTML DOM节点添加自定义主题,标识当前主题
const toggleTheme = (isDarkMode) => {
htmlEl.setAttribute("data-theme", isDarkMode ? "dark" : "light");
};
const themeMedia = window.matchMedia("(prefers-color-scheme: dark)");
// 页面初始化切换
toggleTheme(themeMedia.matches);
// 监听系统切换
themeMedia.addListener((e) => {
toggleTheme(e.matches);
});
⭐️ 页面提供切换按钮,用户主动切换
需要在html节点添加自定义属性,并根据当前主题色通过CSS变量控制。
点击切换按钮后设置自定义属性值即可。
/* 浅色模式 */
html[data-theme="light"]:root {
--body-background: #efefef;
}
/* 深色模式 */
html[data-theme="dark"]:root {
--body-background: #000;
}
body {
background: var(--body-background);
transition: background 0.3s;
}
const htmlEl = document.documentElement;
const buttonEl = document.getElementById("btn");
buttonEl.addEventListener("click", () => {
const currentTheme = htmlEl.getAttribute("data-theme");
const nextTheme = currentTheme === "dark" ? "light" : "dark";
htmlEl.setAttribute("data-theme", nextTheme);
});
⭐️ 通过URL控制当前主题
页面加载后根据URL query参数动态添加到html节点自定义属性,并根据当前主题色通过CSS变量控制。
const search = new URLSearchParams(location.search);
const theme = search.get("theme") || "light";
document.documentElement.setAttribute("data-theme", theme);
上面三种场景结合起来,基本满足目前多主题所有需求。
在线DEMO: codesandbox.io/s/multiple-…
如果项目中没有使用UI库或使用了支持CSS变量主题适配的UI库,可以本章内容,请直接参考上面技术方案探索。
根据上面「多主题技术方案探索」结论,我们从「UI库适配」和「自定义样式适配」来介绍下页面如何从0到1实现多主题适配。
先放一张最终实现效果图,源码已放到 github 仓库,有条件的看官可以边看源码,边阅读下面的示例代码
基于Ant Design具体讲UI库如何实现多主题方案。对于其他不支持的UI库(Element UI等等),实现的思路大致相同。
共分为三个步骤:
通过配置深色和浅色两套主题文件,分别对需要自定义样式的less变量赋值。最终构建两套主题样式,分别加上属性选择器前缀。
# 文件目录结构
.
├── src
│ └── theme
│ ├── antd.css # 构建产物
│ ├── antd.custom.variable.less # 自定义antd less变量
│ ├── antd.dark.base.less # 自定义 antd 深色主题
│ ├── antd.light.base.less # 自定义 antd 浅色主题
│ ├── antd.less # 构建入口文件
└── theme.sh
构建两套样式无疑增加了构建产物大小,最终构建两套样式文件大小约为1.4M,gzip后300K左右。
如果你的项目是刚启动并且比较小,可以使用支持CSS变量的UI库。
如果项目预期会很庞大,而且希望使用antd周边生态比较完善的库,那么我建议你做这件事情。
⭐️ 配置多主题样式
antd.custom.variable.less 自定义antd less变量文件
为什么要单独设置一份antd的less变量设置,由于上面提到过的:antd作为老项目基本都支持CSS变量,主题方案是通过less变量实现的,所以我们要自己设置不同主题的less变量。
@live-primary-color: #ff0040;
// default
@live-body-background: #efefef;
@live-text-color: #666;
// dark
@live-body-background-dark: #000;
@live-text-color-dark: #bfbfbf;
antd.dark.base.less 自定义 antd 深色主题
@import './antd.custom.variable.less';
@import '../../node_modules/antd/lib/style/themes/dark.less';
@import '../../node_modules/antd/dist/antd.less';
// 覆盖antd less变量值
@primary-color: @live-primary-color;
@body-background: @live-body-background-dark;
antd.light.base.less 自定义 antd 浅色主题
@import "./antd.custom.variable.less";
@import "../../node_modules/antd/lib/style/themes/default.less";
@import "../../node_modules/antd/dist/antd.less";
// 覆盖antd less变量值
@primary-color: @live-primary-color;
@body-background: @live-body-background;
构建:分别构建浅色和深色主题
# '编译暗黑主题样式'
npx lessc --js ./src/theme/antd.dark.base.less ./src/theme/antd.dark.base.css
# '编译白色主题样式'
npx lessc --js ./src/theme/antd.default.base.less ./src/theme/antd.default.base.css
构建产物:antd.dark.base.css antd.default.base.css
⭐️ 自定义UI库样式
variable.css 自定义CSS变量
此文件用于自定义样式和UI库样式的CSS变量合集
:root {
--live-primary-color: #ff0040;
--live-font-size-base: 14px;
--live-font-size-lg: 16px;
--live-font-size-sm: 12px;
}
html[data-theme="default"]:root {
--live-body-background: #efefef;
}
html[data-theme="dark"]:root {
--live-body-background: #000;
}
ant.less 自定义UI库样式文件
@import (less) "./variable.css";
html[data-theme="default"] {
@import (less) "./antd.default.base.css";
}
html[data-theme="dark"] {
@import (less) "./antd.dark.base.css";
}
html[data-theme="dark"],
html[data-theme="default"] {
.ant-btn {
font-size: var(--font-size-lg);
&-lg {
font-size: 18px;
}
&-sm {
font-size: var(--font-size-base);
}
}
}
构建:给浅色和深色分别添加作用域,并加入自定义UI样式。
因为我们整体的切换主题要结合html标签的自定义属性 data-theme 的值为 light 或 dark 来实现,所以要结合构建的浅色和深色的的两份主题文件添加作用域。
npx lessc --js -clean-css ./src/theme/antd.less ./src/theme/antd.css
构建产物: antd.css ,在项目head标签中引入,就完成了UI库的主题适配。
因为「UI库主题适配实现」中,variable.css设置了CSS变量,所以自定义样式的节点上直接使用var(CSS变量)即可。
<div style="color: var(--text-color)"></div>
本篇文章重点讲「不支多主题的UI库」适配,相信未来所有的UI库都会支持CSS变量实现多主题切换,目前antd正在做这件事,等完全支持后,多主题适配需要关心的是自定义UI库样式和自定义样式主题适配。
如果你有更好的主题适配方案,欢迎一起讨论。
*请认真填写需求信息,我们会在24小时内与您取得联系。