注册
web

🎨 CSS 写到手抽筋?Stylus 说:‘让我来!’

前言

还在手动重复写 margin: 0; padding: 0;?还在为兼容性疯狂加 -webkit- 前缀?大厂前端早已不用原始 CSS 硬刚了!Stylus 作为一款现代化 CSS 预处理器,让你写样式像写 JavaScript 一样爽快。

Stylus:高效的CSS预处理器

基本特性

Stylus是一种CSS预处理器,提供了许多CSS不具备的高级功能:

// 定义变量
$background_color = rgba(255, 255, 255, 0.95)

.wrapper
background $background_color
box-shadow 0 0 0 10px rgba(0, 0, 0, 0.1)

优势与使用场景

  1. 变量支持:避免重复值,便于主题切换
  2. 嵌套规则:更清晰的DOM结构表示
  3. 混合(Mixins) :复用样式块
  4. 函数与运算:动态计算样式值
  5. 简洁语法:可选的花括号、分号和冒号

编译与使用

安装Stylus后,可以通过命令行编译.styl文件:

npm install -g stylus
stylus -w common.styl -o common.css
  1. 第一个语句是用来安装stylus的直接运行就好
  2. 第二个语句是你编译common.styl文件时使用的,也就是你写CSS代码时使用的,因为浏览器并不能直接编译.styl文件,所以你要先将.styl文件编译成.css文件,也就是用上面给的那个命令,注意要自己切换成自己的.styl文件名,后面的css名可以随便取一个自己想要的

插件的使用

我们要想使用stylus,除了要全局安装之外还要下载一下下面的这个插件。

我们要先进入插件市场,然后搜索stylus,点击我选择的那个插件点击安装即可

image.png

案例实战

先看效果,再上代码,最后在分析考点易错点

效果

下面是我们实现的一个简单的效果界面图

image.png

代码

$background_color = rgba(255, 255, 255, 0.95)

html
box-sizing border-box
min-height 100vh
display flex
flex-direction column
justify-content center
align-items center
text-align center
background url('http://wes.io/hx9M/oh-la-la.jpg') center no-repeat
background-size cover

*
box-sizing border-box

.wrapper
padding 20px
min-width 350px
background $background_color
box-shadow 0 0 0 10px rgba(0, 0, 0, 0.1)
h2
text-align center
margin 0
font-weight 200


body
color pink

.plates
margin 0
padding 0
text-align left
list-style: none
li
border-bottom 1px solid rgba(0, 0, 0, 0.2)
padding 10px 0px
display flex
label
flex 1
cursor pointer
input
display none


.add-items
margin-top 20px
input
padding 10px
outline 0
border 1px solid rgba(0, 0, 0, 0.1)

我们可以看到.styl文件不用去写:{}了,而且可以直接层叠样式

当我们运行stylus -w common.styl -o common.css命令时,它会实时的将common.styl文件编译成common.css,你可以根据自己的需求来编写,让我们看看它帮我写好的common.css文件吧

html {
box-sizing: border-box;
min-height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
background: url("http://wes.io/hx9M/oh-la-la.jpg") center no-repeat;
background-size: cover;
}
* {
box-sizing: border-box;
}
.wrapper {
padding: 20px;
min-width: 350px;
background: rgba(255,255,255,0.95);
box-shadow: 0 0 0 10px rgba(0,0,0,0.1);
}
.wrapper h2 {
text-align: center;
margin: 0;
font-weight: 200;
}
body {
color: #ffc0cb;
}
.plates {
margin: 0;
padding: 0;
text-align: left;
list-style: none;
}
.plates li {
border-bottom: 1px solid rgba(0,0,0,0.2);
padding: 10px 0px;
display: flex;
}
.plates label {
flex: 1;
cursor: pointer;
}
.plates input {
display: none;
}
.add-items {
margin-top: 20px;
}
.add-items input {
padding: 10px;
outline: 0;
border: 1px solid rgba(0,0,0,0.1);
}
// 获取DOM元素
// 获取添加项目的表单元素
const addItems = document.querySelector('.add-items');
// 获取显示项目列表的元素
const itemsList = document.querySelector('.plates');
// 从本地存储获取项目数据,如果没有则初始化为空数组
let items = JSON.parse(localStorage.getItem('tapasItems')) || [];

// 添加新项目函数
function addItem(e) {
// 阻止表单默认提交行为
e.preventDefault();
// 获取输入框中的文本值
const text = this.querySelector('[name=item]').value;
// 创建新项目对象
const item = {
text, // 项目文本
done: false // 完成状态初始为false
};
// 将新项目添加到数组中
items.push(item);
// 更新列表显示
populateList(items, itemsList);
// 将更新后的数组保存到本地存储
localStorage.setItem('tapasItems', JSON.stringify(items));
// 重置表单
this.reset();
}

// 渲染项目列表函数
function populateList(plates = [], platesList) {
// 使用map方法将数组转换为HTML字符串
platesList.innerHTML = plates.map((plate, i) => {
return `


${i} id="item${i}" ${plate.done ? 'checked' : ''}>

${i}">${plate.text}

`
;
}).join(''); // 将数组转换为字符串
}

// 切换项目完成状态函数
function toggleDone(e) {
// 如果点击的不是input元素则直接返回
if (!e.target.matches('input')) return;
// 获取被点击元素的data-index属性值
const el = e.target;
const index = el.dataset.index;
// 切换项目的完成状态
items[index].done = !items[index].done;
// 更新本地存储
localStorage.setItem('tapasItems', JSON.stringify(items));
// 重新渲染列表
populateList(items, itemsList);
}

// 添加事件监听器
// 表单提交事件 - 添加新项目
addItems.addEventListener('submit', addItem);
// 列表点击事件 - 切换项目完成状态
itemsList.addEventListener('click', toggleDone);

// 初始化加载 - 页面加载时渲染已有项目
populateList(items, itemsList);
html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover">
<title>Documenttitle>
<link rel="stylesheet" href="./common.css">
head>
<body>
<div class="wrapper">
<h2>Local TAPASh2>
<p>请添加您的TAPASp>
<ul class="plates">
<li>Loading Tapas ...li>
ul>
<form action="" class="add-items">
<input
type="text"
placeholder="Item Name"
required --
让输入框变成必须填写 -->
name="item"
>
<input type="submit" value="+ Add Item">
form>
div>

<script src="./common.js">

script>
body>
html>

分析考点易错点

1. Stylus 变量 $background_color

考点

  • Stylus 中变量的定义和使用
  • RGBA 颜色值的表示方法

答案

  • $background_color = rgba(255, 255, 255, 0.95) 定义了一个半透明白色背景变量
  • 在 Stylus 中,变量名可以包含 $ 符号,但不是必须的
  • 可以直接在样式中引用变量,如 background $background_color

易错点

  • 忘记变量名前加 $(虽然 Stylus 允许不加,但加了更清晰)
  • RGBA 值写错格式,如漏掉 alpha 通道或使用错误范围值
  • 变量作用域问题(Stylus 变量有作用域概念)

2. 背景图片设置

考点

  • CSS 背景属性的简写方式
  • background-size: cover 的作用
  • 多背景属性的正确顺序

答案

background url('http://wes.io/hx9M/oh-la-la.jpg') center no-repeat
background-size cover

等价于 CSS:

background-image: url('http://wes.io/hx9M/oh-la-la.jpg');
background-position: center;
background-repeat: no-repeat;
background-size: cover;

易错点

  • 混淆 cover 和 contain 的区别:

    • cover:完全覆盖容器,可能裁剪图片
    • contain:完整显示图片,可能留白
  • 背景图片 URL 未加引号导致错误
  • 多个背景属性顺序错误(简写时有特定顺序要求)
  • 忘记设置 no-repeat 导致图片平铺

3. localStorage 使用

考点

  • localStorage 的 API 使用
  • JSON 序列化与反序列化
  • 数据持久化策略

答案

// 存储数据
localStorage.setItem('tapasItems', JSON.stringify(items));

// 读取数据
let items = JSON.parse(localStorage.getItem('tapasItems')) || [];

易错点

  • 忘记使用 JSON.stringify 直接存储对象,导致存储为 [object Object]
  • 读取时忘记使用 JSON.parse,导致得到的是字符串而非对象
  • 未处理 getItem 返回 null 的情况(代码中使用 || [] 做了默认值处理)
  • 存储大量数据超出 localStorage 容量限制(通常 5MB)
  • 不考虑隐私模式下 localStorage 可能不可用的情况

4. Viewport Meta 标签

考点

  • 响应式设计基础
  • 移动端视口控制
  • 各属性的含义

答案

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no, viewport-fit=cover">

各属性含义:

  • width=device-width:视口宽度等于设备宽度
  • initial-scale=1:初始缩放比例为1
  • user-scalable=no:禁止用户缩放
  • viewport-fit=cover:覆盖整个屏幕(针对刘海屏设备)

易错点

  • 拼写错误如 user-scalable 写成 user-scalabe
  • 错误理解 initial-scale 的作用
  • 在需要用户缩放功能的场景错误地设置 user-scalable=no
  • 忽略 viewport-fit=cover 导致刘海屏设备显示问题
  • 多个属性间缺少逗号分隔(viewport 内容是用逗号分隔的)

小知识

最后再讲一个我也是刚刚才了解到的小知识,毕竟我还是小白嘛🚀🚀

  1. 首先打开自己的手机开启热点,然后用自己的电脑连接手机上的热点
  2. 在电脑上按住Win+R键,输入cmd,进入终端

image.png 3. 在终端中输入ipconfig的命令,找到一个名为IPv4的地址,复制一下

image.png

  1. 然后运行html文件,要用Open with Live Serve运行项目

image.png

  1. 将你之前复制的IPv4的地址更改到下面的位置,也就是在我图片的127.0.0.1的位置上填写上你自己之前复制的地址

image.png

  1. 之后可以先运行一下,运行成功的话,将这整个链接复制发给你的手机,然后你手机点击这个链接就可以登录上这个网页了。
  2. 如果出现了一些BUG,有可能是防火墙的问题,或者你没有IPv4的地址,那就在终端的那个页面复制一个你显示了的地址就可以了,如果是其它问题自行上网搜索吧,小白的我也解决不了🚀🚀

作者:绅士玖
来源:juejin.cn/post/7516797727066406966

0 个评论

要回复文章请先登录注册