Emotion中Sibling Selectors(兄弟选择器)无法正常工作问题
问题:Emotion Styled组件的兄弟选择器不生效
我用Emotion写了一个CardContainer组件,代码如下:
const CardContainer = styled(Flex)` flex-direction: column; padding: 12px; width: 100%; max-width: 450px; height: auto; border-radius: 32px; overflow: hidden; z-index: 1; background: rgba(218, 228, 242); box-shadow: 4px 4px 12px 2px rgba(black, 0.6); transition: 0.2s; &:not(:first-child) { background: red; margin-left: -50px; } &:hover, &:focus-within { transform: translatey(-1rem); } &:hover ~ &, &:focus-within ~ & { transform: translatex(50px); } `;
其中最后一段&:hover ~ &的样式完全不生效,我想要实现的是原生CSS里这种效果:
.card:hover ~ .card, .card:focus-within ~ .card { transform: translatex(50px); }
原因
Emotion生成的styled组件会给每个实例分配唯一的作用域类名,&在样式里指代的是这个唯一类名。所以&:hover ~ &会被解析成类似.css-xxxx:hover ~ .css-xxxx的选择器,但兄弟CardContainer实例的类名是不同的(比如.css-yyyy),自然匹配不到,样式就不会生效。而原生CSS里用的是同一个.card类名,所有兄弟元素都共享这个类,所以能正常匹配。
解决方案
给组件指定一个全局的自定义类名,然后用这个类名来写兄弟选择器:
- 修改styled组件的样式代码,改用自定义类名编写兄弟选择器:
const CardContainer = styled(Flex)` /* 原有基础样式保留不变 */ flex-direction: column; padding: 12px; width: 100%; max-width: 450px; height: auto; border-radius: 32px; overflow: hidden; z-index: 1; background: rgba(218, 228, 242); box-shadow: 4px 4px 12px 2px rgba(black, 0.6); transition: 0.2s; &:not(:first-child) { background: red; margin-left: -50px; } &:hover, &:focus-within { transform: translatey(-1rem); } /* 替换为自定义类名的兄弟选择器 */ &:hover ~ .card, &:focus-within ~ .card { transform: translatex(50px); } `;
- 使用组件时给每个实例加上统一的类名:
<CardContainer className="card">卡片内容1</CardContainer> <CardContainer className="card">卡片内容2</CardContainer> <CardContainer className="card">卡片内容3</CardContainer>
这样就能实现和原生CSS一致的效果:当某个卡片hover或获得焦点时,它后面的所有兄弟卡片都会向右平移50px。
内容的提问来源于stack exchange,提问作者goplay
相关产品推荐
相关产品推荐

