条件样式
了解如何在 Chakra 中使用条件样式和响应式样式。
概述
Chakra 允许您使用条件样式属性为伪状态、媒体查询和自定义数据属性编写样式。
用法
例如,以下是如何在按钮悬停时更改其背景颜色
<Box bg="red.500" _hover={{ bg: "red.700" }}>
Hover me
</Box>
嵌套条件
条件值可以嵌套以创建复杂的选择器规则。
以下是如何在悬停时改变元素聚焦时的背景颜色
<Box bg={{ base: "red.500", _hover: { _focus: "red.700" } }}>
Hover & Focus me
</Box>
At 规则
这也适用于支持的 at 规则 (@media
, @layer
, @container
, @supports
, 和 @page
)
<Box
css={{
"@container (min-width: 10px)": {
color: "green.300",
},
}}
>
Hello
</Box>
伪类
悬停、活动、焦点和禁用
以下是关于如何设置元素的悬停、活动、焦点和禁用状态的样式示例
<chakra.button
_hover={{ bg: "red.700" }}
_active={{ bg: "red.900" }}
_focus={{ bg: "red.800" }}
_disabled={{ opacity: "0.5" }}
>
Hover me > Hover me
</chakra.button>
第一个、最后一个、奇数、偶数
以下是关于如何设置列表中第一个、最后一个、奇数和偶数元素的样式示例
<Box as="ul">
{items.map((item) => (
<Box
as="li"
key={item}
_first={{ color: "red.500" }}
_last={{ color: "red.800" }}
>
{item}
</Box>
))}
</Box>
您还可以使用 _even
和 _odd
修饰符来设置偶数和奇数元素的样式
<table>
<tbody>
{items.map((item) => (
<chakra.tr key={item} _even={{ bg: "gray.100" }} _odd={{ bg: "white" }}>
<td>{item}</td>
</chakra.tr>
))}
</tbody>
</table>
伪元素
之前和之后
要设置元素的 ::before
和 ::after
伪元素的样式,请使用 _before
和 _after
修饰符
<Box _before={{ content: '"👋"' }} _after={{ content: '"🥂"' }}>
Hello
</Box>
占位符
要设置任何输入或文本区域的占位符文本样式,请使用 _placeholder
修饰符
<chakra.input
placeholder="Enter your name"
_placeholder={{ color: "gray.500" }}
/>
文件输入
要设置文件输入按钮的样式,请使用 _file
修饰符
<chakra.input
type="file"
_file={{ bg: "gray.500", px: "4", py: "2", marginEnd: "3" }}
/>
媒体查询
减少动画
使用 _motionReduce
和 _motionSafe
修饰符根据用户的动画偏好来设置元素样式
<Box _motionSafe={{ transition: "all 0.3s" }}>Hello</Box>
配色方案
prefers-color-scheme
媒体特性用于检测用户是否要求系统使用浅色或深色主题。
使用 _osLight
和 _osDark
修饰符根据用户的配色方案偏好来设置元素样式
<chakra.div bg={{ base: "white", _osDark: "black" }}>Hello</chakra.div>
颜色对比度
prefers-contrast
媒体特性用于检测用户是否要求系统使用高对比度或低对比度主题。
使用 _highContrast
和 _lessContrast
修饰符根据用户的颜色对比度偏好来设置元素样式
<Box bg={{ base: "white", _highContrast: "black" }}>Hello</Box>
方向
orientation
媒体特性用于检测用户设备是处于竖屏模式还是横屏模式。
使用 _portrait
和 _landscape
修饰符根据用户的设备方向来设置元素样式
<Box pb="4" _portrait={{ pb: "8" }}>
Hello
</Box>
选择器
任意选择器
对于任意选择器,使用 css
prop 为一次性选择器编写样式
<Box css={{ "&[data-state=closed]": { color: "red.300" } }} />
这是另一个针对父元素子元素的示例
<Box
css={{
"& > *": { margin: "2" },
}}
/>
组选择器
要根据其父元素的状态或属性来设置元素的样式,请将 group
类添加到父元素,并在子元素上使用任何 _group*
修饰符。
<div className="group">
<Text _groupHover={{ bg: "red.500" }}>Hover me</Text>
</div>
此修饰符适用于所有伪类修饰符,例如 _groupHover
, _groupActive
, _groupFocus
, 和 _groupDisabled
等。
兄弟选择器
要根据其兄弟元素的状态或属性来设置元素的样式,请将 peer
类添加到兄弟元素,并在目标元素上使用任何 _peer*
修饰符。
<div>
<p className="peer">Hover me</p>
<Box _peerHover={{ bg: "red.500" }}>I'll change by bg</Box>
</div>
注意:这仅适用于带有 peer
标记的元素是前一个兄弟元素,即它位于您要开始的元素之前。
数据属性
从左到右和从右到左
要根据文本方向设置元素样式,请使用 _ltr
和 _rtl
修饰符
<div dir="ltr">
<Box _ltr={{ ml: "3" }} _rtl={{ mr: "3" }}>
Hello
</Box>
</div>
状态
要根据元素的 data-{state}
属性设置样式,请使用相应的 _{state}
属性
<Box data-loading _loading={{ bg: "gray.500" }}>
Hello
</Box>
这适用于常见状态,例如 data-active
, data-disabled
, data-focus
, data-hover
, data-invalid
, data-required
, 和 data-valid
。
<Box data-active _active={{ bg: "gray.500" }}>
Hello
</Box>
方向
要根据元素的 data-orientation
属性设置样式,请使用 _horizontal
和 _vertical
修饰符
<Box
data-orientation="horizontal"
_horizontal={{ bg: "red.500" }}
_vertical={{ bg: "blue.500" }}
>
Hello
</Box>
ARIA 属性
要根据元素的 aria-{state}=true
属性设置样式,请使用相应的 _{state}
prop
<Box aria-expanded="true" _expanded={{ bg: "gray.500" }}>
Hello
</Box>
参考
以下是您可以在 Chakra 中使用的所有条件属性的列表
条件名称 | 选择器 |
---|---|
_hover (悬停) | @media (hover: hover)&:is(:hover, [data-hover]):not(:disabled, [data-disabled]) |
_active (活动) | &:is(:active, [data-active]):not(:disabled, [data-disabled], [data-state=open]) |
_focus (焦点) | &:is(:focus, [data-focus]) |
_focusWithin (焦点内部) | &:is(:focus-within, [data-focus-within]) |
_focusVisible (可见焦点) | &:is(:focus-visible, [data-focus-visible]) |
_disabled (禁用) | &:is(:disabled, [disabled], [data-disabled], [aria-disabled=true]) |
_visited (已访问) | &:visited |
_target (目标) | &:target |
_readOnly (只读) | &:is([data-readonly], [aria-readonly=true], [readonly]) |
_readWrite (读写) | &:read-write |
_empty (空) | &:is(:empty, [data-empty]) |
_checked (选中) | &:is(:checked, [data-checked], [aria-checked=true], [data-state=checked]) |
_enabled (启用) | &:enabled |
_expanded (展开) | &:is([aria-expanded=true], [data-expanded], [data-state=expanded]) |
_highlighted (高亮) | &[data-highlighted] |
_complete (完成) | &[data-complete] |
_incomplete (未完成) | &[data-incomplete] |
_dragging (拖拽中) | &[data-dragging] |
_before (之前) | &::before |
_after (之后) | &::after |
_firstLetter (首字母) | &::first-letter |
_firstLine (首行) | &::first-line |
_marker (标记) | &::marker |
_selection (选择) | &::selection |
_file (文件) | &::file-selector-button |
_backdrop (背景) | &::backdrop |
_first (第一个) | &:first-of-type |
_last (最后一个) | &:last-of-type |
_notFirst (非第一个) | &:not(:first-of-type) |
_notLast (非最后一个) | &:not(:last-of-type) |
_only (唯一的) | &:only-child |
_even (偶数) | &:nth-of-type(even) |
_odd (奇数) | &:nth-of-type(odd) |
_peerFocus (同级焦点) | .peer:is(:focus, [data-focus]) ~ & |
_peerHover (同级悬停) | .peer:is(:hover, [data-hover]):not(:disabled, [data-disabled]) ~ & |
_peerActive (同级活动) | .peer:is(:active, [data-active]):not(:disabled, [data-disabled]) ~ & |
_peerFocusWithin (同级焦点内部) | .peer:focus-within ~ & |
_peerFocusVisible (同级可见焦点) | .peer:is(:focus-visible, [data-focus-visible]) ~ & |
_peerDisabled (同级禁用) | .peer:is(:disabled, [disabled], [data-disabled]) ~ & |
_peerChecked (同级选中) | .peer:is(:checked, [data-checked], [aria-checked=true], [data-state=checked]) ~ & |
_peerInvalid (同级无效) | .peer:is(:invalid, [data-invalid], [aria-invalid=true]) ~ & |
_peerExpanded (同级展开) | .peer:is([aria-expanded=true], [data-expanded], [data-state=expanded]) ~ & |
_peerPlaceholderShown (同级占位符显示) | .peer:placeholder-shown ~ & |
_groupFocus (组焦点) | .group:is(:focus, [data-focus]) & |
_groupHover (组悬停) | .group:is(:hover, [data-hover]):not(:disabled, [data-disabled]) & |
_groupActive (组活动) | .group:is(:active, [data-active]):not(:disabled, [data-disabled]) & |
_groupFocusWithin (组焦点内部) | .group:focus-within & |
_groupFocusVisible (组可见焦点) | .group:is(:focus-visible, [data-focus-visible]) & |
_groupDisabled (组禁用) | .group:is(:disabled, [disabled], [data-disabled]) & |
_groupChecked (组选中) | .group:is(:checked, [data-checked], [aria-checked=true], [data-state=checked]) & |
_groupExpanded (组展开) | .group:is([aria-expanded=true], [data-expanded], [data-state=expanded]) & |
_groupInvalid (组无效) | .group:invalid & |
_indeterminate (不确定) | &:is(:indeterminate, [data-indeterminate], [aria-checked=mixed], [data-state=indeterminate]) |
_required (必需) | &:is([data-required], [aria-required=true]) |
_valid (有效) | &:is([data-valid], [data-state=valid]) |
_invalid (无效) | &:is([data-invalid], [aria-invalid=true], [data-state=invalid]) |
_autofill (自动填充) | &:autofill |
_inRange (在范围内) | &:is(:in-range, [data-in-range]) |
_outOfRange (超出范围) | &:is(:out-of-range, [data-outside-range]) |
_placeholder (占位符) | &::placeholder, &[data-placeholder] |
_placeholderShown (占位符已显示) | &:is(:placeholder-shown, [data-placeholder-shown]) |
_pressed (按下) | &:is([aria-pressed=true], [data-pressed]) |
_selected (选中) | &:is([aria-selected=true], [data-selected]) |
_grabbed (被抓取) | &:is([aria-grabbed=true], [data-grabbed]) |
_underValue (低于值) | &[data-state=under-value] |
_overValue (高于值) | &[data-state=over-value] |
_atValue (在值处) | &[data-state=at-value] |
_default (默认) | &:default |
_optional (可选) | &:optional |
_open (打开) | &:is([open], [data-open], [data-state=open]) |
_closed (关闭) | &:is([closed], [data-closed], [data-state=closed]) |
_fullscreen (全屏) | &is(:fullscreen, [data-fullscreen]) |
_loading (加载中) | &:is([data-loading], [aria-busy=true]) |
_hidden (隐藏) | &:is([hidden], [data-hidden]) |
_current (当前) | &[data-current] |
_currentPage (当前页) | &[aria-current=page] |
_currentStep (当前步骤) | &[aria-current=step] |
_today (今天) | &[data-today] |
_unavailable (不可用) | &[data-unavailable] |
_rangeStart (范围开始) | &[data-range-start] |
_rangeEnd (范围结束) | &[data-range-end] |
_now (现在) | &[data-now] |
_topmost (最顶层) | &[data-topmost] |
_motionReduce (减少动画) | @media (prefers-reduced-motion: reduce) |
_motionSafe (安全动画) | @media (prefers-reduced-motion: no-preference) |
_print (打印) | @media print |
_landscape (横向) | @media (orientation: landscape) |
_portrait (纵向) | @media (orientation: portrait) |
_dark (深色) | .dark &, .dark .chakra-theme:not(.light) & |
_light (浅色) | :root &, .light & |
_osDark (系统深色) | @media (prefers-color-scheme: dark) |
_osLight (系统浅色) | @media (prefers-color-scheme: light) |
_highContrast (高对比度) | @media (forced-colors: active) |
_lessContrast (低对比度) | @media (prefers-contrast: less) |
_moreContrast (高对比度) | @media (prefers-contrast: more) |
_ltr (从左到右) | [dir=ltr] & |
_rtl (从右到左) | [dir=rtl] & |
_scrollbar (滚动条) | &::-webkit-scrollbar |
_scrollbarThumb (滚动条滑块) | &::-webkit-scrollbar-thumb |
_scrollbarTrack (滚动条轨道) | &::-webkit-scrollbar-track |
_horizontal (水平) | &[data-orientation=horizontal] |
_vertical (垂直) | &[data-orientation=vertical] |
_icon (图标) | & :where(svg) |
_starting (起始) | @starting-style |
自定义
Chakra 允许您创建自己的条件,因此您不受默认预设中条件的限制。在此处了解有关自定义条件的更多信息:在此处。