Is it possible to have letter-spacing relative to the font-size and inherit properly?

主宰稳场 提交于 2019-11-30 15:15:25

问题


My question is basically the same as this one, but replace "line-height" with "letter-spacing": When a relative line-height is inherited, it is not relative to the element's font-size. Why? And how do i make it relative?

My use case is like this:

body {
    font-size: 18px;
    letter-spacing: 1.2em; /* I would like letter-spacing to be relative to the font-size across the document, at least until I override it */
}

.small {
    font-size: 14px;
    /* letter-spacing is 1.2em of 18px instead of 14px */
}

I know that the reason it doesn't work is that the computed value, and not the specified value, is inherited, so I have to re-specify the letter-spacing every time the font-size changes. But I'm hoping there's something similar to how unitless values in line-height work.

Sure I can do this:

* {
    letter-spacing: 1.2em;
}

But then I can't stop the cascading at some element, like I would be able to with line-height:

body {
    font-size: 18px;
    line-height: 1.5;
}

.normal-line-height {
    line-height: normal;
    /* all the descendants of this element will have a normal line-height */
}

I mean, SURE, I could always do this...

.normal-letter-spacing, .normal-letter-spacing * {
    letter-spacing: normal;
}

But it's still not as elegant as I would like. I don't think there's an elegant solution to this problem, but I'm asking in case I'm missing something.


回答1:


CSS variables are not widely supported but would do the trick:

body {
  font-size: 18px;
  --spacing: 1.2em;
}
.normal-letter-spacing { /* No need to select `.normal-letter-spacing *` */
  --spacing: normal;
}
body * {
  letter-spacing: var(--spacing);
}
.small {
  font-size: 14px;
}
<div>
  <p>Lorem ipsum</p>
  <p class="small">Lorem ipsum</p>
</div>
<hr />
<div class="normal-letter-spacing">
  <p>Lorem ipsum</p>
  <p class="small">Lorem ipsum</p>
</div>

They work because the value of a custom property computes to the specified value:

Computed value: specified value with variables substituted (but see prose for "invalid variables")

Therefore, unlike what happens with letter-spacing, 1.2em is not transformed to an absolute length.

Then, you can tell all elements to use --spacing as the value of letter-spacing. So 1.2em will be resolved locally with respect of the font size of each element.

Unlike * { letter-spacing: 1.2em; }, this approach sets --spacing: 1.2em only once, in the body, and lets it propagate by inheritance. Therefore, if you want to change that value in a subtree, you only need to override --spacing in the root. You don't have to select all the subtree.




回答2:


I would try to use REM over EM to freeze your relation with one value, which would be root (body) font-size. You wouldn't have to care about changes on font-size later.

If you'd like to use rems in more places I would advice to organise all classes in one place so you wouldn't have much problem with maintaining that. It would also be a good idea to keep it as a utility class like

.txt-spacing-big { letter-spacing: 2rem; }
.txt-spacing-medium { letter-spacing: 1rem; }


来源:https://stackoverflow.com/questions/39692615/is-it-possible-to-have-letter-spacing-relative-to-the-font-size-and-inherit-prop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!