【问题标题】:How percentage truly works compared to other units in different situations与不同情况下的其他单位相比,百分比如何真正起作用
【发布时间】:2021-06-14 04:14:57
【问题描述】:

所以基本上我最近一直在尝试使用 CSS,我遇到了一些对我来说似乎很新的东西。在设置元素的填充时,我通常使用 em 或 px 等单位,但这次我尝试使用百分比,令我惊讶的是,它的工作方式与其他单位截然不同。

所以我设置了三种不同的情况:

body {
  margin: 0;
}
.container {
  display: flex;
  background-color: lightblue;
  justify-content: space-between;
  margin: 30px 0;
}
.flex {
   display: flex;
}
.container a {
  color: #000;
  padding: 50px;
  background-color: rgba(0, 0, 0, 0.3)
}
.container.two {
  background-color: lightgreen;
}
.container.two a {
  padding: 30%;
}
.container.three {
  background-color: beige;
}
.container.three a {
  padding: 30%;
}
<div class="container">
  <div class="flex">
    <a href="#">Item 1</a>
    <a href="#">Item 2</a>
  </div>
  <div class="flex">
    <a href="#">Item 1</a>
    <a href="#">Item 2</a>
  </div>
</div>
<div class="container two">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>
<div class="container three">
  <div>
    <a href="#">Item 9</a>
    <a href="#">Item 10</a>
  </div>
  <div>
    <a href="#">Item 11</a>
    <a href="#">Item 12</a>
  </div>
</div>

在每种情况下,我都有一个导航栏,导航栏的两侧各有 2 个项目。我使用像素和百分比来为项目设置填充。导航栏本身就是弹性容器。在前两种情况下,项目的容器是弹性容器,但第三种不是。

  1. 使用像素(连同 flexbox): 当使用像素和 flexbox 时,我觉得一切都很正常。

  2. 使用百分比(连同弹性框): 所以这就是事情开始变得奇怪的地方。项目被推出导航栏。

  3. 使用百分比(不带 flexbox): 在这里,项目没有被推送到导航栏,而是在它们的直接父级中增长,最终它们开始以更高的百分比值包装。

当我从导航栏中删除 flex 时,一切都变得更奇怪了。

我只是想知道为什么在处理弹性盒时百分比的行为与其他单位不同。我从来没有用百分比来做这样的事情,所以这对我来说很新鲜。我好奇。我怀疑这与弹性盒有关,而不是直接与百分比单位有关。

这是相同的复制品:

https://jsfiddle.net/sLnvzrmb/

【问题讨论】:

  • @Paulie_D 感谢您告诉我,这是我的第一个问题。我现在已经包含了完整的代码。它现在可以完全复制了。
  • 编辑做得很好

标签: html css flexbox


【解决方案1】:

你同时面临很多事情的组合。

首先,与填充一起使用的百分比会将父元素宽度视为参考(而不是元素本身)

百分比是根据生成框的包含块的宽度计算的,即使对于“padding-top”和“padding-bottom”也是如此ref

在我们的例子中,包含块是父元素。

其次,对内联元素应用填充与对块元素应用填充不同。内联元素的顶部和底部填充不会影响布局,但您会有一种重叠:

内联非替换框的垂直内边距、边框和边距从内容区域的顶部和底部开始,与“行高”无关。但在计算行框高度时只使用“行高”。 ref

第三,在使用 flexbox 时,您必须考虑默认的 nowrap 行为 ref 以及 flex 项目被阻止的事实(即使它们的显示设置为内联)

flex item的显示值被blockified .. ref


现在,如果我们考虑使用 flexbox 的第一种情况。这些项目被阻止并且百分比将父宽度视为参考但是您有一个复杂的循环行为案例,因为父(也是弹性项目)的宽度基于其内容。我知道消化所有这些信息并不容易,所以这里有一个分步说明来理解:

.container {
  display: flex;
  background-color: lightblue;
  justify-content: space-between;
}
.flex {
   display: flex;
   border:2px solid red;
}
.container a {
  color: #000;
  background-color: rgba(0, 0, 0, 0.3)
}
.container.two a {
  padding: 30%;
}
Before padding
<div class="container">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>
After padding
<div class="container two">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

仔细查看我添加的红色边框,以及在这两种情况下它的宽度是如何相同的。诀窍是浏览器将首先忽略填充(因为它是一个百分比值)来计算父宽度,然后将使用该宽度来查找填充的值,并且逻辑上你会溢出。溢出等于您拥有的填充(宽度正好是30%*4)。由于默认的 nowrap 行为,元素不会换行,但您可以禁用此功能:

.container {
  display: flex;
  background-color: lightblue;
  justify-content: space-between;
}
.flex {
   display: flex;
   border:2px solid red;
   flex-wrap:wrap;
}
.container a {
  color: #000;
  background-color: rgba(0, 0, 0, 0.3)
}
.container.two a {
  padding: 30%;
}
Before padding
<div class="container">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>
After padding
<div class="container two">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

现在,如果您从父级中删除 display:flex,您将不再拥有弹性项目,现在您处理内联元素并获得以下内容

.container {
  display: flex;
  background-color: lightblue;
  justify-content: space-between;
}
.flex {
   border:2px solid red;
}
.container a {
  color: #000;
  background-color: rgba(0, 0, 0, 0.3)
}
.container.two a {
  padding: 30%;
}
Before padding
<div class="container">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>
After padding
<div class="container two">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

与以前相同的逻辑,首先定义宽度,然后用作参考,但您不会溢出,因为内联元素将换行到下一行并且您将在行之间重叠,因为 padding-top/bottom 没有' t 适用于内联元素。

添加inline-block 看看区别

.container {
  display: flex;
  background-color: lightblue;
  justify-content: space-between;
}
.flex {
   border:2px solid red;
}
.container a {
  color: #000;
  display:inline-block;
  background-color: rgba(0, 0, 0, 0.3)
}
.container.two a {
  padding: 30%;
}
Before padding
<div class="container">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>
After padding
<div class="container two">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

最后,如果你从导航栏中移除 flexbox,作为 flex 项目的父元素现在是一个块元素,它的宽度不再基于它的内容,但它现在默认是全宽,你有

.container {
  background-color: lightblue;
  justify-content: space-between;
  width:100px;
}
.flex {
   border:2px solid red;
}
.container a {
  color: #000;
  background-color: rgba(0, 0, 0, 0.3)
}
.container.two a {
  padding: 30%;
}
Before padding
<div class="container">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>
After padding
<div class="container two">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

bigger width
<div class="container two" style="width:300px">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

full width
<div class="container two" style="width:auto">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

所以我们的父元素是全宽的,padding:30% 就是基于那个宽度。想象一下它会有多大,因为每个元素都有 60% 的填充(左 + 右),所以总共有 120%。而且我们的元素是内联元素,所以顶部和底部不会应用,只会重叠

使用inline-block 并禁用overalp,现在顶部和底部是布局的一部分:

.container {
  background-color: lightblue;
  justify-content: space-between;
  width:100px;
}
.flex {
   border:2px solid red;
}
.container a {
  color: #000;
  display:inline-block;
  background-color: rgba(0, 0, 0, 0.3)
}
.container.two a {
  padding: 30%;
}
Before padding
<div class="container">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>
After padding
<div class="container two">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

bigger width
<div class="container two" style="width:300px">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

full width
<div class="container two" style="width:auto">
  <div class="flex">
    <a href="#">Item 5</a>
    <a href="#">Item 6</a>
  </div>
  <div class="flex">
    <a href="#">Item 7</a>
    <a href="#">Item 8</a>
  </div>
</div>

【讨论】:

  • 感谢您的回答。所以基本上当使用像素时,容器的宽度会随着内容的变化而变化。但是当使用百分比时,宽度不会改变,这会导致溢出。
  • @vio 仅在容器的宽度取决于内容宽度的情况下,当您具有循环依赖并且浏览器首先必须忽略百分比以查找父项的宽度时。说到像素,我们没有这个问题,因为像素不是相对单位
【解决方案2】:

如果你指定一个 div 的宽度为百分比,它指的是 div 父级计算宽度的百分比,当你指定 viewport 时它指的是窗口屏幕的百分比。另一方面,像素是绝对单位,它们不像百分比那样是相对的。这就是百分比对 flexbox 的作用不同的主要原因,而不仅仅是 flexbox,而是所有东西。 请参阅本文的一些文章以供参考: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Values_and_Units https://developer.mozilla.org/en-US/docs/Web/CSS/percentage

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-24
相关资源
最近更新 更多