通常,你需要控制子组件内部的样式。比如我们想要将这些盒子变成红色、绿色和蓝色。
实现这一点的一种方法是使用 :global CSS 修饰符,它允许你无差别地定位其他组件内的元素:
App
<style>
	.boxes :global(.box:nth-child(1)) {
		background-color: red;
	}
	.boxes :global(.box:nth-child(2)) {
		background-color: green;
	}
	.boxes :global(.box:nth-child(3)) {
		background-color: blue;
	}
</style>但是有很多理由不应该这样做。首先,它非常冗长。其次,它很脆弱 —— 对 Box.svelte 实现细节的任何改变都可能破坏选择器。
最重要的是,这样做很粗暴。组件应该能够自己决定哪些样式可以从”外部”控制,就像它们决定哪些变量作为 props 暴露出去一样。:global 应该作为一个后备方案 —— 最后的手段。
在 Box.svelte 中,将 background-color 修改为通过 CSS 自定义属性 来决定:
Box
<style>
	.box {
		width: 5em;
		height: 5em;
		border-radius: 0.5em;
		margin: 0 0 1em 0;
		background-color: var(--color, #ddd);
	}
</style>任何父元素(比如 <div class="boxes">)都可以设置 --color 的值,我们也可以在单个组件上设置它:
App
<div class="boxes">
	<Box --color="red" />
	<Box --color="green" />
	<Box --color="blue" />
</div>这些值可以像其他任何属性一样是动态的。
这个特性通过在需要时将每个组件包裹在一个带有
display: contents的元素中来实现,并将自定义属性应用于它。如果你检查元素,你会看到像这样的标记:<svelte-css-wrapper style="display: contents; --color: red;"> <!-- contents --> </svelte-css-wrapper>由于
display: contents的存在,这不会影响你的布局,但是这个额外的元素可能会影响像.parent > .child这样的选择器。
1
2
3
4
5
6
7
8
9
<script>
import Box from './Box.svelte';
</script>
<div class="boxes">
<Box />
<Box />
<Box />
</div>