Stylus 自定义函数 #
函数基础 #
函数与混入类似,但函数主要用于计算和返回值,而不是直接输出样式。
定义函数 #
stylus
// 定义函数
add(a, b)
a + b
// 使用函数
.element
width add(100px, 50px) // 150px
height add(50px, 50px) // 100px
函数 vs 混入 #
stylus
// 混入:输出样式
border-radius(radius)
-webkit-border-radius radius
border-radius radius
.box
border-radius(5px) // 直接输出样式
// 函数:返回值
calculate-rem(px)
(px / 16) * 1rem
body
font-size calculate-rem(16) // 返回 1rem
参数 #
基本参数 #
stylus
// 多参数函数
spacing(multiplier, base = 8px)
base * multiplier
.element
padding spacing(2) // 16px
margin spacing(3, 10px) // 30px
默认参数 #
stylus
// 默认参数
font-size(size = 16px)
size
// 使用默认值
body
font-size() // 16px
h1
font-size(32px) // 32px
命名参数 #
stylus
// 命名参数
gradient(direction, start-color, end-color)
linear-gradient(direction, start-color, end-color)
// 使用命名参数
.hero
background gradient(start-color: #3498db, end-color: #2ecc71, direction: to right)
剩余参数 #
stylus
// 收集剩余参数
sum(numbers...)
total = 0
for n in numbers
total = total + n
total
.element
width sum(10px, 20px, 30px) // 60px
返回值 #
基本返回 #
stylus
// 返回计算值
double(value)
value * 2
.element
width double(50px) // 100px
条件返回 #
stylus
// 根据条件返回不同值
text-color(bg-color)
if lightness(bg-color) > 50%
#333
else
#fff
.button
background-color #3498db
color text-color(#3498db) // #fff
.card
background-color #f5f5f5
color text-color(#f5f5f5) // #333
多值返回 #
stylus
// 返回列表
sizes(base)
(base base * 1.25 base * 1.5)
.element
font-size sizes(16px)[0] // 16px
line-height sizes(16px)[1] // 20px
// 返回对象
theme-colors()
(primary: #3498db, secondary: #2ecc71, danger: #e74c3c)
colors = theme-colors()
.button
background-color colors.primary
实用函数示例 #
1. 单位转换 #
stylus
// px 转 rem
px-to-rem(px, base = 16)
(px / base) * 1rem
// px 转 em
px-to-em(px, base = 16)
(px / base) * 1em
// rem 转 px
rem-to-px(rem, base = 16)
unit(rem * base, 'px')
// 使用
body
font-size px-to-rem(16) // 1rem
h1
font-size px-to-rem(32) // 2rem
.element
padding px-to-em(16, 14) // 1.1428em
2. 颜色函数 #
stylus
// 生成对比色
contrast-color(color)
if lightness(color) > 50%
darken(color, 80%)
else
lighten(color, 80%)
// 生成悬停色
hover-color(color, amount = 10%)
if lightness(color) > 50%
darken(color, amount)
else
lighten(color, amount)
// 生成活跃色
active-color(color, amount = 20%)
if lightness(color) > 50%
darken(color, amount)
else
lighten(color, amount)
// 使用
.button
background-color #3498db
&:hover
background-color hover-color(#3498db) // #2980b9
&:active
background-color active-color(#3498db) // #1f6dad
3. 数学函数 #
stylus
// 百分比计算
percentage(value, total)
(value / total) * 100%
// 网格宽度
grid-width(columns, total-columns = 12, gutter = 30px, container = 1200px)
(container - (total-columns - 1) * gutter) / total-columns * columns + (columns - 1) * gutter
// 使用
.col-6
width percentage(6, 12) + '%' // 50%
.sidebar
width grid-width(3) // 277.5px
4. 字符串函数 #
stylus
// 拼接类名
class-name(prefix, name)
'.' + prefix + '-' + name
// 生成选择器
bem-selector(block, element = null, modifier = null)
selector = '.' + block
if element
selector = selector + '__' + element
if modifier
selector = selector + '--' + modifier
selector
// 使用
{bem-selector('card', 'header')}
padding 15px
{bem-selector('card', 'body')}
padding 20px
{bem-selector('card', null, 'featured')}
border-color #3498db
5. 列表函数 #
stylus
// 获取列表第一个元素
first(list)
list[0]
// 获取列表最后一个元素
last(list)
list[-1]
// 列表长度
list-length(list)
length(list)
// 列表是否包含某值
contains(list, value)
for item in list
if item == value
return true
false
// 使用
colors = #3498db #2ecc71 #e74c3c
.primary
color first(colors) // #3498db
.danger
color last(colors) // #e74c3c
6. 对象函数 #
stylus
// 获取对象键
keys(obj)
result = ()
for key in obj
push(result, key)
result
// 获取对象值
values(obj)
result = ()
for key, value in obj
push(result, value)
result
// 深度合并对象
merge-objects(obj1, obj2)
result = {}
for key, value in obj1
result[key] = value
for key, value in obj2
if typeof(value) == 'object' and typeof(result[key]) == 'object'
result[key] = merge-objects(result[key], value)
else
result[key] = value
result
// 使用
theme = {
primary: #3498db,
secondary: #2ecc71
}
theme-keys = keys(theme) // (primary secondary)
theme-values = values(theme) // (#3498db #2ecc71)
7. 响应式函数 #
stylus
// 断点检查
breakpoints = {
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
}
// 获取断点值
get-breakpoint(name)
breakpoints[name]
// 计算响应式字体
responsive-font(min-size, max-size, min-width = 320px, max-width = 1200px)
"calc(%s + %s * ((100vw - %s) / %s))" % (min-size (max-size - min-size) min-width (max-width - min-width))
// 使用
.container
+media-up(get-breakpoint('md'))
max-width 720px
.title
font-size responsive-font(16px, 32px)
8. 验证函数 #
stylus
// 检查是否为有效颜色
is-valid-color(value)
if typeof(value) == 'rgba' or typeof(value) == 'color'
true
else
false
// 检查是否为正数
is-positive(value)
value > 0
// 检查是否在范围内
in-range(value, min, max)
value >= min and value <= max
// 使用
safe-color(color, fallback = #333)
if is-valid-color(color)
color
else
fallback
.element
color safe-color(#3498db) // #3498db
background-color safe-color(invalid, #fff) // #fff
高级函数技巧 #
递归函数 #
stylus
// 阶乘
factorial(n)
if n <= 1
1
else
n * factorial(n - 1)
// 斐波那契数列
fibonacci(n)
if n <= 1
n
else
fibonacci(n - 1) + fibonacci(n - 2)
// 使用
.element
z-index factorial(5) // 120
函数缓存 #
stylus
// 使用变量缓存计算结果
_cache = {}
cached-calculation(key, fn)
if key in _cache
_cache[key]
else
result = fn()
_cache[key] = result
result
函数组合 #
stylus
// 组合多个函数
compose(fn1, fn2)
(x) => fn1(fn2(x))
// 使用
double(x) = x * 2
add-one(x) = x + 1
double-then-add = compose(add-one, double)
.element
width double-then-add(10px) // 21px
函数最佳实践 #
1. 单一职责 #
stylus
// 推荐:每个函数只做一件事
px-to-rem(px)
(px / 16) * 1rem
px-to-em(px, base)
(px / base) * 1em
// 不推荐:函数做太多事
convert-unit(value, unit, base = 16)
// 太多逻辑...
2. 有意义的命名 #
stylus
// 推荐:描述性命名
calculate-grid-width(columns)
contrast-text-color(bg-color)
// 不推荐:无意义命名
calc1(c)
helper(x)
3. 提供默认值 #
stylus
// 推荐:常用参数有默认值
spacing(multiplier, base = 8px)
base * multiplier
// 不推荐:无默认值
spacing(multiplier, base)
base * multiplier
下一步 #
掌握自定义函数后,继续学习 条件语句 了解如何在样式中使用条件判断!
最后更新:2026-03-28