[书签] CSS:使用缩进和缩进

如果网页的几个元素彼此靠近,则用户会感觉到这些元素有一些共同之处。元素分组可通过评估元素之间的距离来帮助用户理解其关系。如果所有元素都位于彼此相同的距离处,则用户将难以浏览页面以找出哪些元素彼此相关,哪些元素彼此无关。 本文致力于您需要了解的有关设置元素之间的距离以及设置元素内部空间的所有知识。特别是,我们将讨论在哪些情况下值得使用内部填充,以及在哪种情况下-外部(边距)。




CSS距离类型


元素及其部分之间的距离(可通过CSS进行自定义)有两种类型。关于元素,它们分为内部和外部。想象一下,我们有一个要素。如果在其内部某些零件之间存在一定距离,则这是一个内部凹痕。如果我们在谈论单个元素之间的距离-这是外部缩进。


内层空间和外层空间

在CSS中,元素及其组件之间的距离可以如下调整:

.element {
    padding: 1rem;
    margin-bottom: 1rem;
}

该属性padding在此处用于调整缩进,而该属性margin用于配置缩进。一切都非常简单。真相?但是,如果使用包含许多小零件和子组件的组件,则在CSS中调整距离可能会非常复杂。

▍保证金属性-缩进


该属性margin用于设置各个元素之间的距离。例如,上一个示例使用CSS属性margin-bottom: 1rem在一个位于另一个之上的两个元素之间添加垂直距离。

可以为元素的四个侧面(顶部,右侧,底部,左侧-顶部,右侧,底部,左侧)设置外部缩进。因此,在继续进行示例和讨论不同的距离设置方式之前,重要的是要阐明一些基本概念。

▍折叠外部填充


如果我们用简单的词语描述“外部边距的崩溃”的概念,那么可以说,如果一个位于另一个上方的两个元素都具有外部边距,并且其中一个的缩进大于另一个的缩进,则会发生这种情况。在这种情况下,将使用较大的缩进,而较小的缩进将被忽略。


越大压痕获胜。

另外,在上述图中,属性是上部元件和所述属性上配置margin-bottom在下一个margin-top。元素之间的垂直距离对应于这些凹口中的较大者。

为了避免这个问题,建议配置中的所有元素(如所描述的相同缩进这里)。这是另一个有趣的事实。 CSS Tricks资源对属性的使用进行了投票。事实证明,该物业赢得了61%的选票。 解决此问题的方法如下:margin-bottommargin-topmargin-bottom



.element:not(:last-child) {
    margin-bottom: 1rem;
}

使用CSS选择器:not可以轻松删除最后一个子元素的外部缩进,以消除元素之间不必要的空间。

这是一个使用外边距演示,

另一个与折叠外边距有关的示例与子元素和父元素有关。假设您具有以下HTML:

<div class="parent">
  <div class="child">I'm the child element</div>
</div>

这是他的风格:

.parent {
  margin: 50px auto 0 auto;
  width: 400px;
  height: 120px;
}

.child {
  margin: 50px 0;
}

这是可视化所有这些结果的结果。


子级和父级

请注意,子级紧靠父级的顶部。这是其外边缘崩溃的结果。根据 W3C,有几种解决此问题的方法:

  • border父元素添加属性
  • display子元素的属性设置为value inline-block

解决此问题的一种更容易理解的方法是设置padding-top父元素的属性


设置父元素的顶部缩进

eg负缩进


负值可用于任何外部缩进。在某些情况下,此技术非常有用。看下图。


设置父元素的padding属性的结果

父元素具有属性padding: 1rem这会导致子对象的顶部,左侧和右侧偏移。但是孩子必须与父母的边界相邻。负外边距将有助于实现这一目标。

.parent {
    padding: 1rem
}

.child {
    margin-left: -1rem;
    margin-right: -1rem;
    margin-top: -1rem;
}

这就是这种风格化的结果。


负外边距有助于达到预期效果

这是一个演示

如果您对负外边距主题感兴趣,我建议您这篇文章。

▍填充属性-内部填充


如前所述,该属性padding允许您控制元素内部的空间。应用此属性的目的取决于使用它的情况。

例如,它可用于增加链接周围的空间。这导致可点击链接空间的增加


缩进为绿色

the填充属性不起作用的情况


重要的是要注意,垂直缩进不适用于具有属性的元素display: inline例如,这些是元素<span><a>如果配置padding此类元素的属性,则此元素上的此类设置将不起作用。这只是一个友好的提醒,内联元素需要更改属性display

.element span {
    display: inline-block;
    padding-top: 1rem;
    padding-bottom: 1rem;
}

CSS网格布局元素之间的空间


在CSS网格中,您可以使用属性轻松调整列和行之间的距离grid-gap这是定义列和行之间距离的属性的缩写。


行与列之间的距离

.element {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-gap: 16px; /*    16px     */
}

这些属性的完整记录如下所示:

.element {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-row-gap: 24px;
    grid-column-gap: 16px;
}

Flexbox布局的CSS元素之间的空间


建议为网格和弹性框布局建议一个属性。这是一个属性gap目前,只有Firefox 支持

.element {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

而且,此属性不能与CSS @supports一起使用来确定它是否受支持并基于此做出适当的决定。如果您喜欢此属性,请投票将其添加到Chrome。

CSS中的定位元素


也许元素的位置不能直接归因于调整元素之间距离的方法,但是在某些情况下,位置起着作用。例如,如果有一个绝对定位的子元素需要位于16px父元素的左边缘和上边缘。

考虑以下示例。在卡片上有一个图标,该图标需要放置在距父元素的顶部和左侧边缘一定距离的位置。要实现此效果,可以使用以下样式:

.category {
    position: absolute;
    left: 16px;
    top: 16px;
}



父元素和子元素的边界之间的距离以绿色突出显示。

使用方案和案例研究


在本节中,我们将介绍使用方法来调整元素之间的距离的方案。CSS的日常工作中很可能会遇到类似的情况。

▍标头组件



组件是具有以下设置的标题:左右缩进,徽标周围的空间,导航元素周围的空间,导航元素与用户名之间的距离。

在这种情况下,标题组件具有徽标,导航区域和显示信息的区域关于用户个人资料。您能猜出这种元素的样式代码应该是什么样的吗?在这里,为了简化起见,此元素的示意图标记:

<header class="c-header">
  <h1 class="c-logo"><a href="#">Logo</a></h1>
  <div class="c-header__nav">
    <nav class="c-nav">
      <ul>
        <li><a href="#">...</a></li>
      </ul>
    </nav>
    <a href="#" class="c-user">
      <span>Ahmad</span>
      <img class="c-avatar" src="shadeed.jpg" alt="">
    </a>
  </div>
</header>



内页边距和外页边距

使用左右页边距。它们的目的是确保标题的内容不紧贴其边缘。

.c-header {
    padding-left: 16px;
    padding-right: 16px;
}

设置导航链接时,必须考虑以下事实:每个导航链接在垂直和水平方向上都应有足够的内部空间。因此,其可点击区域将足够大,这将改善项目可访问性

.c-nav a {
    display: block;
    padding: 16px 8px;
}

如果我们讨论元素之间的距离,则可以使用属性margin,或者-可以将display元素的属性更改<li>inline-block因此,由于将这样的元素视为符号,因此在处于相同水平的元素之间添加了较小的空间。

.c-nav li {
    /*     ,     */
    display: inline-block;
}

最后,用户名和头像具有左外部缩进。

.c-user img,
.c-user span {
    margin-left: 10px;
}

请注意,如果要创建多语言网站,则在这种情况下,建议使用逻辑 CSS属性:

.c-user img,
.c-user span {
    margin-inline-start: 1rem;
}



分隔符前后的距离不一样,

请注意分隔符前后的距离不一样。原因是未设置导航块的宽度。相反,此处仅配置内部缩进。结果,导航元素的宽度取决于它们的内容。以下是此问题的解决方案:

  • 设置导航项目的最小宽度。
  • 增加水平压痕。
  • 在分隔符的左侧添加一个额外的缩进。

最好和最简单的方法是使用第三种方法,即配置属性margin-left

.c-user {
    margin-left: 8px;
}

这是一个演示

grid网格布局中的距离-CSS Flexbox


网格布局是经常使用调整元素之间距离的技术的地方。考虑以下示例。


网格布局

我们需要调整表格的行和列之间的距离。这是标记:

<div class="wrapper">
    <div class="grid grid--4">
        <div class="grid__item">
              <article class="card"><!--   --></article>
        </div>
        <div class="grid__item">
              <article class="card"><!--   --></article>
        </div>
        <!--   .. -->
    </div>
</div>

我通常更喜欢将组件保持在封装状态,并避免设置它们的外部缩进。因此,我有一个元素可以grid_item放置card元素。

.grid--4 {
    display: flex;
    flex-wrap: wrap;
}

.grid__item {
    flex-basis: 25%;
    margin-bottom: 16px;
}

多亏了此CSS代码,每行中将有四张卡片。这是一种调整它们之间距离的可能方法:

.grid__item {
    flex-basis: calc(25% - 10px);
    margin-left: 10px;
    margin-bottom: 16px;
}

通过使用CSS函数,calc()可以从中减去缩进flex-basis如您所见,这不是一个简单的解决方案。我实际上更喜欢以下内容:

  • 设置网格项目的属性padding-left
  • 将父元素设置为具有margin-left与y相同的负外边距padding-left

多年前,我在这里阅读一些文章的名称后,就已经了解了这种方法(如果您知道哪种文章,请告诉我)。

.grid--4 {
    display: flex;
    flex-wrap: wrap;
    margin-left: -10px;
}

.grid__item {
    flex-basis: 25%;
    padding-left: 10px;
    margin-bottom: 16px;
}

我在这里使用负值的原因margin-left是因为第一张卡片具有padding-left实际上不需要的属性结果,我将wrapper元素移到左侧,并消除了不必要的空间。

→  这是一个工作示例,

另一个类似的想法是使用缩进和负缩进。这是来自Facebook网站的示例。


内边距和外边距

这是说明此想法的CSS代码:

.wrapper {
    margin-left: -4px;
    margin-right: -4px;
}

.story {
    padding-left: 4px;
    padding-right: 4px;
}

grid网格布局中的距离-CSS Grid


而现在-最好的部分!在基于CSS Grid的布局中,使用property可以非常方便地调整元素之间的距离grid-gap此外,您不必担心元素的宽度和较低的外部边框。CSS网格布局可解决所有这些问题。

.grid--4 {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-gap: 1rem;
}

就这样。我相信没有人会争辩说,设置网格布局比设置Flexbox布局更容易,更容易理解。

only仅在必要时设置元件之间的距离


在网格布局中,我非常喜欢以下事实:grid-gap仅当元素之间必须有一定距离时才应用属性看一下下面的布局。


网格布局,其中移动环境中的元素垂直排列,而桌面中的元素水平排列;

站点的一部分包含两张卡片。我需要在垂直放置卡片的移动环境中和在水平放置卡片的台式机中将它们分开。没有CSS Grid,就无法实现这种布局灵活性。看下面的代码:

.card:not(:last-child) {
    margin-bottom: 16px;
}

@media (min-width: 700px) {
    .card:not(:last-child) {
        margin-bottom: 0;
        margin-left: 1rem;
    }
}

不太方便。真相?那下一个样式呢?

.card-wrapper {
    display: grid;
    grid-template-columns: 1fr;
    grid-gap: 1rem;
}

@media (min-width: 700px) {
    .card-wrapper {
        grid-template-columns: 1fr 1fr;
    }
}

完成了!一切都变得更加简单。

▍使用底部外部压痕


假设我们有以下组件,一个组件位于另一个组件之上。它们每个都有一个较低的外部凹痕。


一组水平排列的组件

注意,最后一个元素有一个底部外部边界。这是错误的,因为缩进仅应在元素之间出现。

您可以通过现在将要分析的解决方案之一来解决此问题。

解决方案1:CSS选择器:不


.element:not(:last-child) {
    margin-bottom: 16px;
}

解决方案2:将同一级别的相邻元素组合在一起


.element + .element {
    margin-top: 16px;
}

决策分析


尽管解决方案#1似乎更具吸引力,但它具有以下缺点:

  • 这会导致特定于CSS的问题。在使用选择器之前无法重新定义它:not
  • 如果一列以上的项目不适用。如下所示。


两列元素和1号解决方案的问题

如果我们谈论2号解决方案,则其应用不会导致特异性问题。的确,此解决方案也仅适用于单列元素的情况。

在这种情况下,最好通过为父元素添加负的外部缩进来决定是否删除不必要的空间:

.wrapper {
    margin-bottom: -16px;
}

在这里发生以下情况。由于此设置,该元素向下移动的距离等于指定的外部压痕。但是在这里,您应该注意不要在元素重叠时设置这样的外部缩进。

▍组件卡


现在,我要详细讨论组件卡的设置。也许最后我会得到一整本书。在这里,我将考虑一种用于配置卡的通用模式,并讨论如何管理它们。


分量卡(如果您想吃东西,对不起),请

考虑一下该卡中元素和它们的零件之间的确切距离。这是我对这个问题的回答。


内边距和外边距

这是标记:

<article class="card">
    <a href="#">
      <div class="card__thumb"><img src="food.jpg" alt=""></div>
      <div class="card__content">
        <h3 class="card__title">Cinnamon Rolls</font></h3>
        <p class="card__author">Chef Ahmad</p>
        <div class="card__rating"><span>4.9</span></div>
        <div class="card__meta"><!-- --></div>
      </div>
    </a>
</article>

这是课程样式card__content

.card__content {
    padding: 10px;
}

由于此处设置了缩进,因此将设置所有子代的偏移量。然后设置外部页边距:

.card__title,
.card__author,
.card__rating {
  margin-bottom: 10px;
}

在设置等级与信息的分离时,我使用了边框:

.card__meta {
    padding-top: 10px;
    border-top: 1px solid #e9e9e9;
}

但是这里我们面临一个问题!边框未绑定到边缘,这是由于父元素与class card__content缩进造成的。


分隔符并不局限于边缘,

您可能已经猜到了负缩进将有助于我们:

.card__meta {
    padding-top: 10px;
    border-top: 1px solid #e9e9e9;
    margin: 0 -10px;
}

但是这里又出了点问题。现在,文本已粘贴到卡的边缘。


分隔符是正常的,但卡中的内容

放置不正确,为解决此问题,需要为卡中的内容配置左右缩进。

.card__meta {
    padding: 10px 10px 0 10px;
    border-top: 1px solid #e9e9e9;
    margin: 0 -10px;
}



该卡已按其应有的配置

这是一个示例

▍文章内容


我确信我们在这里要谈论的是非常非常普遍的情况。这里的重点是文章的内容通常转到CMS(内容管理系统-内容管理系统)的页面,或者是基于Markdown文件自动生成的。您不能在此处指定元素类。

考虑下面的示例,该示例显示了包含标题,段落和图像的混合标记。

<div class="wrapper">
  <h1>Spacing Elements in CSS</h1>
  <p><!-- content --></p>
  <h2><font color="#3AC1EF">Types of Spacing</font></h2>
  <img src="spacing-1.png" alt="">
  <p><!-- content --></p> 
  <p><!-- content --></p> 
  <h2><font color="#3AC1EF">Use Cases</font></h2>
  <p><!-- content --></p> 
  <h3><font color="#3AC1EF">▍Card Component</font></h3> 
  <img src="use-case-card-2.png" alt="">
</div>

为了使它们看起来都不错,这些元素之间的距离应该均匀并且应该负责任地使用。在处理此示例时,我从type-scale.com借用了一些样式

h1, h2, h3, h4, h5 {
  margin: 2.75rem 0 1.05rem;
}

h1 {
  margin-top: 0;
}

img {
  margin-bottom: 0.5rem;
}

这是带有文章正文的页面图。


页面布局以及margin-top和margin-bottom属性的应用

如果元素<p>后跟标题,例如headingTypes of Spacing,则margin-bottom元素的属性<p>将被忽略。如您所料,这是外边距崩溃的结果。

这是一个例子

▍外部压痕(如适用)


看一下下面的布局。


处于正常状态且空间不足的

元素之间的距离太近时,它们看起来不会很好。我使用Flexbox创建了此布局。该技术称为“对齐移位包装”。从这里得知她的名字

.element {
    display: flex;
    flex-wrap: wrap;
}

作为应用该技术的结果,如果观看区域小于特定限制,则执行换行。这是它的外观。


子元素在新行上,

在这里您需要处理一个中间情况,其中两个元素仍然彼此相邻,但它们之间的距离为零。在这种情况下,我更喜欢使用属性margin-right,该属性可以防止元素相互接触并加快响应速度flex-wrap


元素彼此不接触

▍CSS属性编写方式


首先我们引用MDN:“该属性writing-mode设置文本的水平或垂直位置,以及块方向。”

您是否考虑过将外部缩进与属性writing-mode不同于标准的元素一起使用时应如何表现考虑以下示例。


带有垂直页眉的卡片,

样式如下:

.wrapper {
    /*              */
    display: flex;
}

.title {
    writing-mode: vertical-lr;
    margin-right: 16px;
}

割台旋转90度。它和图像之间应该有一个空白空间。事实证明,该属性margin-right在不同的属性值下表现良好writing-mode

这是一个例子,

我相信我们已经介绍了足够多的缩进方案。现在考虑一些有趣的概念。

组件封装


大型设计系统包含许多组件。调整其外部边距是否合乎逻辑?

考虑以下示例。


纽扣

<button class="button">Save Changes</button>
<button class="button button-outline">Discard</button>

我需要在哪里调整按钮之间的距离?我是否需要配置左右按钮的某些属性?也许您可以使用同一级别的相邻元素的组合?

.button + .button {
    margin-left: 1rem;
}

它没有什么好处。如果只有一个按钮怎么办?如果按钮是垂直放置而不是水平放置,在移动设备上如何工作?总的来说,这里我们面临许多难题。

abstract使用抽象组件


解决上述问题的方法是使用抽象的组件,该组件用于将其他组件放置在其中。这里所说,这是管理填充到父元素的职责的一点转变。我们根据这个想法重新考虑前面的示例。


父子组件

<div class="list">
    <div class="list__item">
        <button class="button">Save Changes</button>
    </div>
    <div class="list__item">
        <button class="button button-outline">Discard</button>
    </div>
</div>

请注意,有包装元素。每个按钮都有自己的包装器。

.list {
    display: flex;
    align-items: center;
    margin-left: -1rem; /*       */
}

.list__item {
    margin-left: 1rem;
}

就这样!而且,这个概念很容易应用于任何JavaScript框架。例如:

<List>
  <Button>Save Changes</Button>
  <Button outline>Discard</Button>
</List>

并且使用的JS工具应将每个元素放入其自己的包装器中。

用作分隔器的组件


如果您怀疑自己正确地阅读了标题,请不要犹豫。我们正在谈论用作分隔符的组件。特别是在这里,我指的是这篇文章,文章讨论了避免使用外部缩进而使用分隔符组件的概念。

想象一下,在站点的特定区域中,您需要左外边的尺寸24px同时,对缩进提出了以下要求:

  • 外部缩进不应直接在组件上配置,因为它是已创建的设计系统的一部分。
  • 缩进必须灵活。在一页上可以有一个尺寸X在另一页上可以有一个尺寸Y

在探索新的Facebook设计时,我首先注意到了这一技巧


Facebook Design Separator Element

在这里用作<div>带有内联样式的分隔符元素width: 16px其唯一目的是在left元素和container元素之间添加空白空间。

这是 React培训手册的引文:“但是在现实世界中,我们需要在组件外部定义空间以将组件安排到页面和场景中。在这里,外部凹痕的设置进入了组件代码,从而在组装时调整了组件之间的距离。”

我同意这一点。在大型设计系统中,向组件添加缩进将是不合理的。这将导致代码看起来不太好。

▍分离器组件问题


既然您已经熟悉了分隔器组件的概念,那么我们来谈谈使用它们时可能会发生的一些问题。这是我一直在思考的问题:

  • 分隔符组件如何占用父组件中的空间?他在水平和垂直布局中的表现如何?例如,这样的组件如何将组件垂直和水平分离?
  • 我是否需要根据display父组件(Flexbox,Grid)的属性来设置这些组件的样式

让我们研究这些问题。

separator分离器组件的尺寸


您可以创建一个接受各种参数的分隔器组件。我不是JavaScript开发人员,但我认为这就是所谓的“道具”。考虑以下示例,该示例取自此处

之间有一个分隔符组件HeaderSection

<Header />
<Spacer mb={4} />
<Section />

这里的情况略有不同。在此,分隔符用于在徽标(组件Logo)和组件表示的导航区域之间创建自动可调的距离Link

<Flex>
  <Logo />
  <Spacer m="auto" />
  <Link>Beep</Link>
  <Link>Boop</Link>
</Flex>

看起来使用CSS来实现这样的分隔符非常简单,并且足以使用设计justify-content: space-between但是,如果您需要更改设计怎么办?在这种情况下,您必须更改样式。

看下面的例子。该代码看起来灵活吗?

<Flex>
  <Logo />
  <Link>Beep</Link>
  <Link>Boop</Link>
  <Spacer m="auto" />
  <Link>Boop</Link>
</Flex>

在这种情况下,需要更改样式。

就大小而言,可以说分隔符的大小可以根据父元素的大小进行调整。在上述情况下,创建grow在CSS中设置为值的属性可能是有意义的flex-grow: 1

<Flex>
  <Spacer grow="1" />
</Flex>

pseudo伪元素的使用


我想到的另一个想法是使用伪元素创建分隔符。

.element:after {
    content: "";
    display: block;
    height: 32px;
}

也许我们有机会将伪元素设为分隔符,而不为此使用单独的元素?例如:

<Header spacer="below" type="pseudo" length="32">
  <Logo />
  <Link>Home</Link>
  <Link>About</Link>
  <Link>Contact</Link>
</Header>

到目前为止,我还没有在项目中使用分隔符组件。但我正在寻找对我有用的方案。

CSS数学函数min(),max(),clamp()


缩进可以动态吗?例如,是否可以使用这种压痕,其最小和最大尺寸取决于观察区域的宽度?我可以肯定地回答这个问题。根据CanIUse数据,所有领先的浏览器均支持CSS函数

回顾网格布局,并讨论如何在其中使用动态缩进。

.wrapper {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-gap: min(2vmax, 32px);
}

构造min(2vmax, 32px)表示以下含义:使用等于2vmax但不超过的距离32px

→  这是这种布局视频演示

→  这是一个示例。

这样的灵活性确实令人惊讶。它为我们提供了许多机会来创建动态且灵活的网页布局。

摘要


在本文中,我们研究了使用CSS调整网页元素之间距离的功能,并讨论了管理元素内部空间的问题。希望您发现今天学到的东西对您有用。

亲爱的读者们!您最常使用哪些工具来调整网页元素之间的距离?


All Articles