哪个神奇的CSS会导致<button>和<div>之间text-vertical-align的区别?

lzl*_*31x 16 html css

我发现里面的文字<button>是自动垂直居中的,而里面的文字<div>是顶部对齐的.

我试图找出哪个CSS规则有所不同但失败了.

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;
  font-family: Arial;
}

div {
  text-align: center;
  display: inline-block;
  cursor: default;
  box-sizing: border-box;
}
Run Code Online (Sandbox Code Playgroud)
<div>text text</div>
<button>text text</button>

<div>text text text text</div>
<button>text text text text</button>

<div>text text text text text text</div>
<button>text text text text text text</button>
Run Code Online (Sandbox Code Playgroud)

至于上面的例子,比较Chrome中的所有计算CSS规则,我只能找到一个不同的对 - align-items: stretchfor <div>while align-items: flex-startfor <button>.

但分配align-items: flex-start并没有帮助.所以我完全糊涂了.

令我感到困惑的是,文本 - 垂直对齐是不同的<div>,<button>即使您使用相同的相应值设置所有CSS规则.换句话说,使用相同的CSS规则,<div>并且<button>行为不同.为什么?

引擎盖下的魔力是什么?


我可以垂直居中<div>(下面的例子)中的文字.我只是想知道导致文本垂直对齐之间差异的原因.

也许它不是由特定的CSS规则引起的,而是因为这两个元素的布局算法在浏览器中是不同的?

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;
  font-family: Arial;
}

div { /* basic CSS rules to button-fy  */
  text-align: center;
  display: inline-block;
  cursor: default;
  box-sizing: border-box;
}

/* Magic */
div, button {
  vertical-align: middle;
}

div span {
  display: inline-block;
  position: relative;
  top: 50%;
  -webkit-transform: translateY(-50%);
          transform: translateY(-50%);
}
Run Code Online (Sandbox Code Playgroud)
<div><span>text text</span></div>
<button>text text</button>

<div><span>text text text text</span></div>
<button>text text text text</button>

<div><span>text text text text text text</span></div>
<button>text text text text text text</button>
Run Code Online (Sandbox Code Playgroud)

Pra*_*man 16

由于您正在使用inline-block,您需要使用vertical-align默认值baseline:

魔术CSS:

vertical-align: middle;
Run Code Online (Sandbox Code Playgroud)

以上将解决它:

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;
  font-family: Arial;
  vertical-align: middle;
}

div {
  text-align: center;
  display: inline-block;
  cursor: default;
  box-sizing: border-box;
}
Run Code Online (Sandbox Code Playgroud)
<div>text</div>
<button>text</button>
Run Code Online (Sandbox Code Playgroud)

而对于div要居中的文本,你需要使用line-heightheightdiv.

魔术CSS:

line-height: 4em;
Run Code Online (Sandbox Code Playgroud)

div,
button {
  width: 4em;
  height: 4em;
  background-color: red;
  padding: 0;
  border: 0;
  margin: 1em;
  font-size: 1em;
  font-family: Arial;
  vertical-align: middle;
  line-height: 4em;
}

div {
  text-align: center;
  display: inline-block;
  cursor: default;
  box-sizing: border-box;
}
Run Code Online (Sandbox Code Playgroud)
<div>text</div>
<button>text</button>
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,但我不满意.`line-height`在您的代码中是硬编码的.鉴于这两个标签的默认`vertical-align`都是`baseline`,为什么它们的行为会有所不同? (2认同)

Jul*_*ire 5

如果您查看 Chrome 源代码,您可以了解它是如何工作的,至少对于 Chrome 而言是这样。似乎有一个应用了特定样式的匿名弹性框。这不是那么简单——至少对我来说不是——但是,您仍然可以推断出应用于这个匿名元素的样式。你可以在这里看到:https : //cs.chromium.org/chromium/src/third_party/WebKit/Source/core/layout/LayoutButton.cpp?sq=package : chromium

有趣的部分:

void LayoutButton::updateAnonymousChildStyle(const LayoutObject& child,
                                             ComputedStyle& childStyle) const {
  ASSERT(!m_inner || &child == m_inner);

  childStyle.setFlexGrow(1.0f);
  // min-width: 0; is needed for correct shrinking.
  childStyle.setMinWidth(Length(0, Fixed));
  // Use margin:auto instead of align-items:center to get safe centering, i.e.
  // when the content overflows, treat it the same as align-items: flex-start.
  childStyle.setMarginTop(Length());
  childStyle.setMarginBottom(Length());
  childStyle.setFlexDirection(style()->flexDirection());
  childStyle.setJustifyContent(style()->justifyContent());
  childStyle.setFlexWrap(style()->flexWrap());
  // TODO (lajava): An anonymous box must not be used to resolve children's auto
  // values.
  childStyle.setAlignItems(style()->alignItems());
  childStyle.setAlignContent(style()->alignContent());
}
Run Code Online (Sandbox Code Playgroud)

这给出了这样的东西:

div span {
  display: flex;
  text-align: center; 
  min-width: 0px;
  flex-grow: 1;
  justify-content: center;
  cursor: default;
  margin: 0 auto;
  height: 100%;
  align-items: center;
  align-content: center;
}
Run Code Online (Sandbox Code Playgroud)

然后您只需要将 div 内容包装在该跨度中并应用样式。所有这些规则可能并不都是必要或准确的,但结果似乎还可以:

void LayoutButton::updateAnonymousChildStyle(const LayoutObject& child,
                                             ComputedStyle& childStyle) const {
  ASSERT(!m_inner || &child == m_inner);

  childStyle.setFlexGrow(1.0f);
  // min-width: 0; is needed for correct shrinking.
  childStyle.setMinWidth(Length(0, Fixed));
  // Use margin:auto instead of align-items:center to get safe centering, i.e.
  // when the content overflows, treat it the same as align-items: flex-start.
  childStyle.setMarginTop(Length());
  childStyle.setMarginBottom(Length());
  childStyle.setFlexDirection(style()->flexDirection());
  childStyle.setJustifyContent(style()->justifyContent());
  childStyle.setFlexWrap(style()->flexWrap());
  // TODO (lajava): An anonymous box must not be used to resolve children's auto
  // values.
  childStyle.setAlignItems(style()->alignItems());
  childStyle.setAlignContent(style()->alignContent());
}
Run Code Online (Sandbox Code Playgroud)
div span {
  display: flex;
  text-align: center; 
  min-width: 0px;
  flex-grow: 1;
  justify-content: center;
  cursor: default;
  margin: 0 auto;
  height: 100%;
  align-items: center;
  align-content: center;
}
Run Code Online (Sandbox Code Playgroud)