界面与布局精校教程
UnoCSS 自定义规则与预设
拆解一个工程化预设:从正则匹配、单位转换到边框、间距和颜色规则。
/* eslint-disable no-useless-escape */
// my-preset.ts
import { Preset } from 'unocss'
// 匹配3位,6位 8位的十六进制颜色*****************-
const singleHex = '[0-9a-fA-F]'
// 匹配0-255
// const singleRgb = '(25[0-5]|2[0-4][0-9]|1?[1-9]?[0-9])'
// 颜色字符串
const hex = (prefix: string) => new RegExp(`${prefix}-(${singleHex}{3}|${singleHex}{6}|${singleHex}{8})
UnoCSS 自定义规则与预设 · 知识教程 · Visual Lab
跳到课程内容
)
// const rgb = (prefix: string) => new RegExp(`${prefix}-rgb\\(${singleRgb},${singleRgb},${singleRgb}\\)
UnoCSS 自定义规则与预设 · 知识教程 · Visual Lab
跳到课程内容
)
// const rgba = (prefix: string) => new RegExp(`${prefix}-rgba\\(${singleRgb},${singleRgb},${singleRgb},(1|0?\\.\\d+)\\)
UnoCSS 自定义规则与预设 · 知识教程 · Visual Lab
跳到课程内容
)
// border样式
const bStyle = 'none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset'
// border
const borderHex = () => new RegExp(`b(l|r|t|b)?-(\\d+)-(${bStyle})-(${singleHex}{3}|${singleHex}{6}|${singleHex}{8})
UnoCSS 自定义规则与预设 · 知识教程 · Visual Lab
跳到课程内容
)
// const borderRgba = () => new RegExp(`b(l|r|t|b)-(\\d+)-(${bStyle})-rgba\\(${singleRgb},${singleRgb},${singleRgb},(1|0?\\.\\d+)\\)
UnoCSS 自定义规则与预设 · 知识教程 · Visual Lab
跳到课程内容
)
//返回单位
const getUnit = (a: string, u: string) => {
switch (u) {
case 'f':
return `${a}%`
case 'h':
return `${a}vh`
case 'w':
return `${a}vw`
case 'r':
return `${a}rem`
case 'e':
return `${a}em`
default:
return `${a}px`
}
}
// 返回方位
const getDiretion = (p: string) => {
switch (p) {
case 'l':
case 'left':
return 'left'
case 'r':
case 'right':
return 'right'
case 'b':
case 'bottom':
return 'bottom'
case 't':
case 'top':
return 'top'
case 'h':
case 'height':
return 'height'
case 'width':
case 'w':
return 'width'
case 'mh':
return 'min-height'
case 'mw':
return 'min-width'
case 'lh':
return 'line-height'
default:
return ''
}
}
// 返回4个方向的margin和padding
const getmp = (prefix: string, a?: string, b?: string, c?: string, d?: string) => {
if (d) return `${prefix}t-${a} ${prefix}r${b} ${prefix}b${c} ${prefix}l${d}`
if (c) return `${prefix}t-${a} ${prefix}r${b} ${prefix}b${c}`
if (b) return `${prefix}t-${a} ${prefix}r${b}`
return `${prefix}t-${a}`
}
const getFloat = (num: string, float: string) => (float ? `${num}.${float.slice(1, float.length)}` : num)
export const unoPreset: Preset = {
name: 'my-preset',
rules: [
[
/^line-(\d+)$/,
([, a]) => ({
'-webkit-line-clamp': `${a}`,
overflow: 'hidden',
' word-break': 'break-all',
' text-overflow': 'ellipsis',
display: '-webkit-box',
' -webkit-box-orient': 'vertical',
}),
],
// 颜色3位,6位 8位
[hex(`^color`), ([, a]) => ({ color: `#${a}` })],
[hex(`^bg`), ([, a]) => ({ 'background-color': `#${a}` })],
// [rgb('^color'), ([, a, b, c]) => ({ color: `rgb(${a},${b},${c})` })],
// [rgb('^bg'), ([, a, b, c]) => ({ 'background-color': `rgb(${a},${b},${c})` })],
// [rgba('^color'), ([, a, b, c, d]) => ({ color: `rgba(${a},${b},${c},${d})` })],
// [rgba('^bg'), ([, a, b, c, d]) => ({ 'background-color': `rgb(${a},${b},${c},${d})` })],
[/^fs-(\d+)$/, ([, a]) => ({ 'font-size': `${a}px` })],
[
/^(p|m)(l|r|b|t)-(-)?(\d+)(p\d+)?(f|h|w|r|e)?$/,
([, a, p, d, b, c, u]) => ({ [`${a === 'p' ? 'padding' : 'margin'}-${getDiretion(p)}`]: `${d ? '-' : ''}${getUnit(getFloat(b, c), u)}` }),
],
[
/^(width|w|mw|height|h|mh|top|bottom|right|left|lh)-(\d+)(p\d+)?(f|h|w|r|e)?$/,
([, a, b, c, u]) => ({ [`${getDiretion(a)}`]: getUnit(getFloat(b, c), u) }),
],
[/^(top|bottom|right|left)--(\d+)(p\d+)?(f|h|w|r|e)?$/, ([, a, b, c, u]) => ({ [`${getDiretion(a)}`]: '-' + getUnit(getFloat(b, c), u) })],
[/^br-(\d+)$/, ([, a]) => ({ 'border-radius': `${a}px` })],
[
/^br-(t|b)-(l|r)-(\d+)(p\d+)?(f|h|w|r|e)?$/,
([, a, d, b, c, u]) => ({ [`border-${getDiretion(a)}-${getDiretion(d)}-radius`]: getUnit(getFloat(b, c), u) }),
],
[borderHex(), ([, a, b, c, d]) => ({ [`border${a ? '-' + getDiretion(a) : ''}`]: `${b}px ${c} #${d}` })],
// [borderRgba(), ([, a, b, c, d, e, f, g]) => ({ [`border${a ? '-' + getDiretion(a) : ''}`]: `${b}px ${c} rgba(${d},${e},${f},${g})` })],
[/^scale-(\d+)$/, ([, a]) => ({ transform: `scale(${Number(a) / 10})` })],
[/^translateX-(-)?(\d+)(p\d+)?(f|h|w|r|e)?$/, ([, m, a, c, u]) => ({ transform: `translateX(${m ? '-' : ''}${getUnit(getFloat(a, c), u)})` })],
[/^tran-(\d+)$/, ([, a]) => ({ transition: `all ${Number(a) / 10}s` })],
['poiter', { cursor: 'pointer' }],
['ew-arrow', { cursor: 'ew-resize' }],
['not-allowed', { cursor: 'not-allowed' }],
['grab', { cursor: 'grab' }],
['no-drop', { cursor: 'no-drop' }],
['not-allowed', { cursor: 'not-allowed' }],
['no-select', { 'user-select': 'none' }],
['box-s', { 'box-sizing': 'border-box' }],
['as-s', { 'align-self': 'flex-start' }],
['as-e', { 'align-self': 'flex-end' }],
['as-c', { 'align-self': 'center' }],
['as-b', { 'align-self': 'baseline' }],
['as-st', { 'align-self': 'stretch' }],
['line', { 'border-bottom': '2px solid #CDCDCD' }],
['fw-b', { 'font-weight': 'bold' }],
['f-ac', { 'align-items': ' center' }],
['f-as', { 'align-items': ' flex-start' }],
['f-ae', { 'align-items': ' flex-end' }],
['f-js', { 'justify-content': ' flex-start' }],
['f-jc', { 'justify-content': ' center' }],
['f-je', { 'justify-content': ' flex-end' }],
['f-jsb', { 'justify-content': 'space-between' }],
['f-jsa', { 'justify-content': 'space-around' }],
['fr', { display: 'flex', 'flex-direction': 'row' }],
['fc', { display: 'flex', 'flex-direction': 'column' }],
['fw', { 'flex-wrap': 'wrap' }],
['fb', { 'flex-basis': 'auto' }],
['fg', { 'flex-grow': '0' }],
['fs', { 'flex-shrink': '0' }],
['f-1', { flex: 1 }],
['b-1', { border: '1px solid #626161' }],
['tline', { 'text-decoration': 'line-through' }],
['uline', { 'text-decoration': 'underline' }],
['hidden', { overflow: 'hidden' }],
['f-0', { flex: '0 0 auto' }],
['frr', { display: 'flex', 'flex-direction': 'row-reverse' }],
['scroll-x', { 'overflow-x': 'scroll' }],
['scroll-y', { 'overflow-y': 'scroll' }],
['text-c', { 'text-align': 'center' }],
['text-l', { 'text-align': 'left' }],
['text-r', { 'text-align': 'right' }],
['pos-r', { position: 'relative' }],
['pos-a', { position: 'absolute' }],
['pos-f', { position: 'fixed' }],
['vertical-line', { height: '24px', opacity: 0.53, border: '1px solid rgba(203, 203, 203, 0.47)' }],
],
variants: [
// hover:
matcher => {
if (!matcher.startsWith('hover:')) return matcher
return {
// slice `hover:` prefix and passed to the next variants and rules
matcher: matcher.slice(6),
selector: s => `${s}:hover`,
}
},
],
shortcuts: [
{
'f-ac-jc': 'f-ac f-jc',
'f-ac-je': 'f-ac f-je',
'f-ac-jsb': 'f-ac f-jsb',
'f-ac-jsa': 'f-ac f-jsa',
'btn-hover': 'hover:scale-11 tran-1 ',
},
[/^mtb-(\d+)$/, ([, c]) => `mt-${c} mb-${c}`],
[/^mlr-(\d+)$/, ([, c]) => `ml-${c} mr-${c}`],
[/^ptb-(\d+)$/, ([, c]) => `pt-${c} pb-${c}`],
[/^plr-(\d+)$/, ([, c]) => `pl-${c} pr-${c}`],
[/^br-t-(\d+)$/, ([, c]) => `br-t-l-${c} br-t-r-${c}`],
[/^br-b-(\d+)$/, ([, c]) => `br-b-l-${c} br-b-r-${c}`],
[/^p-(\d+[fhwre]?)(-\d+[fhwre]?)?(-\d+[fhwre]?)?(-\d+[fhwre]?)?$/, ([, a, b, c, d]) => getmp('p', a, b, c, d)],
[/^m-(\d+[fhwre]?)(-\d+[fhwre]?)?(-\d+[fhwre]?)?(-\d+[fhwre]?)?$/, ([, a, b, c, d]) => getmp('m', a, b, c, d)],
],
}