本篇是结合 tailwindcss 的断点在 CSS 层面隐藏元素。如果需要 JS 层隐藏(即完成移除)见我的另一篇文章:写一个 hook 将自适应断点判断逻辑引入 JS - tailwindcss 系列。
问题和背景
在响应式设计中,我们经常会遇到一个元素在移动端隐藏在 PC 端展现,或反之。
我们可以通过 hidden md:xx 来实现,比如将一个 div 元素隐藏可以使用 hidden md:block
:
tsx
<div className="hidden md:block">
如果要将一个 span 隐藏呢?hidden md:inline
,以此类推我们将会出现类似的重复结构,出现重复就意味着"坏味道",可能违反了 DRY
原则。
解决 DRY
问题
我们可以通过 tailwind css 的 plugin 帮我们解决。
方式一 addUtilities
addUtilities
适合生成静态固定可枚举的 className。由浅入深我们先添加一个 class:
js
const plugin = require('tailwindcss/plugin')
module.exports = plugin(function ({ addUtilities, matchUtilities, theme }) {
addUtilities({
'.hidden-mobilex': {
'@apply hidden': {},
'@apply md:block': {},
},
})
})
以上实现了一个 hidden md:block
的替代品 hidden-mobilex
(命名随便取的演示用)。
应用后的效果:

批量添加
改造上述代码一次性添加 4 个:'inline', 'inline-block', 'block', 'flex'
js
const plugin = require('tailwindcss/plugin')
/** @typedef {import('react').CSSProperties['display']} IDisplay */
/** @type {IDisplay[]} */
const values = ['inline', 'inline-block', 'block', 'flex']
module.exports = plugin(function ({ addUtilities, matchUtilities, theme }) {
const batch = values.reduce((acc, display) => {
return {
...acc,
[`.hidden-mobile-${display}`]: {
'@apply hidden': {},
[`@apply md:${display}`]: {},
},
}
}, {})
// console.log('batch:', batch)
addUtilities(batch)
})
batch 长这样:
js
{
".hidden-mobile-inline": {
"@apply hidden": {},
"@apply md:inline": {}
},
".hidden-mobile-inline-block": {
"@apply hidden": {},
"@apply md:inline-block": {}
},
".hidden-mobile-block": {
"@apply hidden": {},
"@apply md:block": {}
},
".hidden-mobile-flex": {
"@apply hidden": {},
"@apply md:flex": {}
}
}
我们加了一个"奇怪"的类型 IDisplay
,作用仅为了智能提示,以此也可以管中窥豹看到实际我们的 display 远不止这四个,所以接下来引入我们本文的重点支持任意 display 值。
方式二 matchUtilities
我们能否像 tailwind 的 padding 既支持 px-1/2/3/4
又支持 px-[14px]
这种动态值,这也是 tailwind 的精髓之一。
matchUtilities
:适合动态值,其实"能动能静"。
我们要实现的效果是:
hidden-mobile-flex
最后生成hidden md:flex
hidden-mobile-[inline-flex]
最后生成hidden md:inline-flex
js
const plugin = require('tailwindcss/plugin')
/** @typedef {import('react').CSSProperties['display']} IDisplay */
/** @type {IDisplay[]} */
const values = ['inline', 'inline-block', 'block', 'flex']
module.exports = plugin(function ({ matchUtilities }) {
matchUtilities(
{
'hidden-mobile': (value) => {
// console.log('value:', value)
return {
'@apply hidden': {},
[`@apply md:${value}`]: {},
}
},
},
{
values,
},
)
})
通过 values 在 VSCode 安装 tailwind 插件后,能智能提示 values 中列举的值,同时我们输入的动态值,也能应用(当然此处没有禁止非法值,也无需因为应用后 CSS 不生效)。
应用后的效果:

👆 `hidden-mobile-flex` 最后生成 `hidden md:flex`

👆 `hidden-mobile-[inline-flex]` 最后生成 `hidden md:inline-flex`
你还可以这么写,即手写 md:xx 部分,实际不推荐,但是这种写法可以帮助我们了解 tailwind 的生成机制。
diff
const plugin = require('tailwindcss/plugin')
/** @typedef {import('react').CSSProperties['display']} IDisplay */
/** @type {IDisplay[]} */
const values = ['inline', 'inline-block', 'block', 'flex']
module.exports = plugin(function ({ matchUtilities, theme }) {
matchUtilities(
{
'hidden-mobile': (value) => {
console.log('value:', value)
return {
'@apply hidden': {},
+ [`@media (min-width: ${theme('screens.md')})`]: {
+ display: value,
+ },
}
},
},
{
values,
},
)
})
这里很巧妙的用到了 ${theme('screens.md')
而非写死 768px
,值得大家体会。
改进
暂无