本文经作者授权翻译,来源:https://ishadeed.com,作者:Ahmad Shadeed

如果两个或多个元素很接近,那么用户就会认为它们以某种方式属于彼此。当对多个设计元素进行分组时,用户可以根据它们之间的空间大小来决定它们之间的关系。没有间距,用户将很难浏览页面并知道哪些内容相关而哪些内容无关。

在本文中,我将介绍有关CSS中的间距,实现此间距的不同方法以及何时使用 padding 或 margin 所需的所有知识。

CSS中的间距有两种类型,一种在元素外部,另一种在元素内部。对于本文,我将其称为outerinner。假设我们有一个元素,它内部的间距是inner,外部的间距是outer

在CSS中,间距可以如下:

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

我使用 padding 来填充内部间距,使用 margin 来填充外部间距。很简单,不是吗?但是,当处理具有许多细节和子元素的组件时,这会变得越来越复杂。

margin 外部间距

它用于增加元素之间的间距。例如,在上一个示例中,我添加了 margin-bottom:1rem 在两个堆叠的元素之间添加垂直间距。

由于可以沿四个不同的方向(top、right、 bottom、left)添加margin,因此在深入研究示例和用例之前,一定要阐明一些基本概念,这一点很重要。

margin 折叠

简而言之,当两个垂直元素具有margin,并且其中一个元素的margin大于另一个元素时,发生边距折叠。在这种情况下,将使用更大的margin,而另一个将被忽略。

在上面的模型中,一个元素有 margin-bottom,另一个元素有 margin-top,边距较大的元素获胜。

为避免此类问题,建议按照本文使用单向边距。此外,CSS Tricks还在页边距底部和页边距顶部之间进行了投票。61%的开发者更喜欢 margin-bottom 而不是 margin-top

请在下面查看如何解决此问题:

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

使用 :not CSS选择器,您可以轻松地删除最后一个子元素的边距,以避免不必要的间距。

另一个与边距折叠相关的例子是子节点和父节点。让我们假设如下:

I'm the child element
.parent {  margin: 50px auto 0 auto;  width: 400px;  height: 120px;}.child {  margin: 50px 0;}

请注意,子元素固定在其父元素的顶部。那是因为它的边距折叠了。根据W3C,以下是针对该问题的一些解决方案:

  • 在父元素上添加 border
  • 将子元素显示更改为 inline-block

一个更直接的解决方案是将 padding-top 添加到父元素。

负margin

它可以与四个方向一起使用以留出余量,在某些用例中非常有用。让我们假设以下内容:

父节点具有 padding:1rem,这导致子节点从顶部、左侧和右侧偏移。但是,子元素应该紧贴其父元素的边缘。负margin可以助你一臂之力。

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

如果您想更多地挖负margin,建议阅读这篇文章。

padding 内部间距

如前所述,padding在元素内部增加了一个内间距。它的目标可以根据使用的情况而变化。

例如,它可以用于增加链接之间的间距,这将导致链接的可点击区域更大。

必须提出的是,垂直方向的padding对于那些具有 display:inline 的元素不适用,比如 或 。如果添加了内边距,它不会影响元素,内边距将覆盖其他内联元素。

这只是一个友好的提醒,应该更改内联元素的 display 属性。

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

在CSS网格中,可以使用 grid-gap 属性轻松在列和行之间添加间距。这是行和列间距的简写。

.element {  display: grid;  grid-template-columns: 1fr 1fr;  grid-gap: 16px; /* 为行和列都增加了16px的间隙。 */}

gap属性可以使用如下:

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

gap 是一个提议的属性,将用于CSS Grid和flexbox,撰写本文时,它仅在Firefox中受支持。

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

它可能不是直接的元素间距方式,但在一些设计案例中却起到了一定的作用。例如,一个绝对定位的元素需要从其父元素的左边缘和上边缘定位 16px

考虑以下示例,带有图标的卡片,其图标应与其父对象的左上边缘隔开。在这种情况下,将使用以下CSS:

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

在这一节中,你将回顾一下在日常工作中,你在处理CSS项目时,会遇到的不同用例。

header 组件

在这种情况下,标题具有logo,导航和用户个人资料。你能猜出CSS中的间距应该如何设置吗?好吧,让我为你添加一个骨架模型。

Logo

... Ahmad

Header的左侧和右侧都有padding,这样做的目的是防止内容物紧贴在边缘上。

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

对于导航,每个链接在垂直和水平侧均应具有足够的填充,因此其可单击区域可以很大,这将增强可访问性。

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

对于每个项目之间的间距,您可以使用 margin 或将 的 display 更改为 inline-block。内联块元素在它的兄弟元素之间添加了一点空间,因为它将元素视为字符。

.c-nav li {  /* 这将创建你在骨架中看到的间距 */  display: inline-block;}

最后,头像(avatar)和用户名的左侧有一个空白。

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

请注意,如果你要构建多语言网站,建议使用如下所示的CSS逻辑属性。

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

请注意,分隔符周围的间距现在相等,原因是导航项没有特定的宽度,而是具有padding。结果,导航项目的宽度基于其内容。以下是解决方案:

  • 设置导航项目的最小宽度
  • 增加水平padding
  • 在分隔符的左侧添加一个额外的margin

最简单,更好的解决方案是第三个解决方案,即添加 margin-left

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

网格系统中的间距:Flexbox

网格是间隔最常用的情况之一。考虑以下示例:

间距应在列和行之间。考虑以下HTML标记:

通常,我更喜欢将组件封装起来,并避免给它们增加边距。由于这个原因,我有 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,其 padding-left 值相同。

几年前,我从CSS Wizardy那里学到了上述解决方案(我忘记了文章标题,如果您知道,请告诉我)。

.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故事的一个示例:

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

网格系统中的间距:CSS Grid

现在,到了激动人心的部分!使用CSS Grid,你可以很容易地使用 grid-gap 添加间距。此外,你不需要关心网格项的宽度或底部空白,CSS Grid 为你做者一切!

就是这样!难道不是那么容易和直接吗?

按需定制

我真正喜欢CSS Grid 的地方是 grid-gap 只在需要的时候才会被应用。考虑下面的模型。

没有CSS网格,就不可能拥有这种灵活性。首先,请参见以下内容:

.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;  }}

完成了!容易得多。

处理底部margin

假设以下组件堆叠在一起,每个组件都有底边距。

注意最后一个元素有一个空白,这是不正确的,因为边距只能在元素之间。

可以使用以下解决方案之一解决此问题:

解决方案1-CSS :not 选择器

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

解决方案2:相邻兄弟组合器

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

虽然解决方案1具有吸引力,但它具有以下缺点:

  • 它会导致CSS的特异性问题。在使用 :not 选择器之前不可能覆盖它。
  • 万一设计中有不止一列,它将无法正常工作。参见下图。

关于解决方案2,它没有CSS特异性问题。但是,它只能处理一个列栈。

更好的解决方案是通过向父元素添加负边距来取消不需要的间距。

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

它用一个等于底部间距的值将元素推到底部。注意不要超过边距值,因为它会与同级元素重叠。

Card组件

Oh,如果我想把所有细节的Card组件间距都写进去的话,最后可能会出现书本上的内容。我就突出一个大概的模式,看看间距应该如何应用。

你能想到此卡片在哪里使用间距吗?参见下图。

      

Cinnamon Rolls

Chef Ahmad

4.9

.card__content {  padding: 10px;}

上面的 padding 将向其中的所有子元素添加一个偏移量。然后,我将添加所有边距。

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

对于评分和 .car__meta 元素之间的分隔线,我将添加它作为边框。

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

糟糕!由于对父元素 .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文件自动生成的,因此无法为元素添加类。

考虑下面的示例,其中包含标题,段落和图像。

Spacing Elements in CSS

Types of Spacing

Use Cases

Card Component

为了使它们看起来不错,间距应保持一致并谨慎使用。我从type-scale.com借了一些样式。

h1, h2, h3, h4, h5 {  margin: 2.75rem 0 1.05rem;}h1 {  margin-top: 0;}img {  margin-bottom: 0.5rem;}

如果一个 后面有一个标题,例如“Types of Spacing”,那么 的 margin-bottom 将被忽略。你猜到了,那是因为页边距折叠。

Just In Case Margin

我喜欢把这个叫做 "Just in case" margin,因为这就是字面意思。考虑一下下面的模型图。

当元素靠近的时候,它们看起来并不好看。我是用flexbox搭建的。这项技术称为“对齐移位包装”,我从CSS Tricks中学到了它的名称。

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

当视口尺寸较小时,它们的确以新行结尾。见下文:

需要解决的是中间设计状态,即两件物品仍然相邻,但两件物品之间的间距为零的设计状态。在这种情况下,我倾向于向元素添加一个 margin-right,这样可以防止它们相互接触,从而加快 flex-wrap 的工作速度。

CSS 书写模式

根据MDN:

writing-mode CSS属性设置了文本行是水平还是垂直排列,以及块的前进方向。

你是否曾经考虑过将边距与具有不同 writing-mode 的元素一起使用时应如何表现?考虑以下示例。

.wrapper {  /* 使标题和食谱在同一行 */  display: flex;}.title {  writing-mode: vertical-lr;  margin-right: 16px;}

标题被旋转了90度,在它和图像之间应该有一个空白区。结果表明,基于 writing-mode 的页边距工作得非常好。

我认为这些用例就足够了。让我们继续一些有趣的概念!

组件封装

大型设计系统包含许多组件。向其直接添加边距是否合乎逻辑?

考虑以下示例。

Save ChangesDiscard

按钮之间的间距应在哪里添加?是否应将其添加到左侧或右侧按钮?也许你可以如下使用相邻同级选择器:

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

这是不好的。如果只有一个按钮的情况怎么办?或者,当它垂直堆叠时在移动设备上将如何工作?很多很多的复杂性。

解决上述问题的一种方法是使用抽象的组件,其目标是托管其他组件,就像Max Stoiber所说的那样,这是将管理边距的责任移到了父元素上,让我们以这种思维方式重新思考以前的用例。

Save Changes
Discard

注意,我添加了一个包装器,并且每个按钮现在都包装在其自己的元素中。

.list {  display: flex;  align-items: center;  margin-left: -1rem; /* 取消第一个元素的左空白 */}.list__item {  margin-left: 1rem;}

就是这样!而且,将这些概念应用到任何JavaScript框架中都相当容易。例如:

Save Changes  Discard

你使用的JavaScript工具应该将每个项包装在自己的元素中。

是的,你没看错。我在这篇文章中讨论了避免margin的概念,并使用间隔组件来代替它们。

让我们假设一个区域需要从左到右24px的空白,并记住这些限制:

  • margin不能直接用于组件,因为它是一个已经构建的设计系统。
  • 它应该是灵活的。间距可能在X页上,但不在Y页上。

我在检查Facebook的新设计CSS时首先注意到了这一点。

那是一个

,内联样式宽度:16px,它唯一的作用是在左边缘和包装器之间增加一个空白空间。

引述这本React游戏手册中的内容。

但在现实世界中,我们确实需要组件之外的间距来合成页面和场景,这就是margin渗入组件代码的地方:用于组件的间距组合。

我同意。对于大型设计系统,不断向组件添加margin是不可伸缩的,这将最终导致一个令人毛骨悚然的代码。

间隔组件的挑战

现在你了解了间隔组件的概念,让我们深入研究使用它们时遇到的一些挑战。这是我想到的一些问题:

间隔组件如何在父级内部取其宽度或高度?在水平布局和垂直布局中,它将如何工作?我们是否应该根据其父项的显示类型(Flex,Grid)对它们进行样式设置

让我们一一解决上述问题。

调整间隔组件的大小

可以创建一个接受不同变化和设置的间隔。我不是JavaScript开发人员,但我认为他们将其称为Props。考虑来自styled-system.com的以下内容。

我们在一个header和一个 section之间有一个隔板。

虽然这个有点不一样,一个间隔器在logo和导航之间建立一个自动间隔。

Beep  Boop

你可能会认为,通过添加 justify-content:space-between,使用CSS做到这一点相当容易。

如果设计上需要改一下怎么办?那么,如果是这样的话,样式就应该改了。

见下文,你看到那里的灵活性了吗?

Beep  Boop  Boop

那么,如果是这样的话,就应该改变样式。你看出来有什么灵活性了吗?对于尺寸调整部分,可以根据其母体的尺寸调整间隔的尺寸。

对于上面的内容,也许你可以做一个叫 grow 的prop,可以计算成 flex-grow:1 在CSS中。

使用伪元素

我考虑过的另一个想法是使用伪元素创建间隔符。

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

也许我们可以选择通过一个伪元素而不是一个单独的元素来添加间隔器?例如:

Home  About  Contact

直到今天,我还没有在项目中使用间隔组件,但是我期待可以使用它们的用例。

有可能有动态的边距吗?例如,根据视口宽度设置具有最小值和最大值的空白。答案是肯定的!我们可以。最近,Firefox 75支持CSS数学函数,这意味着根据CanIUse在所有主流浏览器中都支持CSS数学函数。

让我们回想一下Grid用例,以了解如何在其中使用动态间距。

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

下面是 min(2vmax,32px) 的意思:使用一个等于 2vmax 的间隙,但不能超过 32px

拥有这样的灵活性确实令人惊讶,并且为我们提供了构建更多动态和灵活布局的许多可能性。

如果对你有所启发和帮助,可以点个关注、收藏、转发,也可以留言讨论,这是对作者的最大鼓励。

作者简介:Web前端工程师,全栈开发工程师、持续学习者。

私信回复大礼包送某网精品视频课程网盘资料,准能为你节省不少钱!

css grid随页面大小_CSS中的间距知识总结,前端开发中各种间距的使用及优缺点相关推荐

  1. css grid随页面大小_前端开发中各种设置CSS间距的优点缺点及实例「实践」

    前言 如果两个或多个元素很接近,那么用户就会认为它们以某种方式属于彼此.当对多个设计元素进行分组时,用户可以根据它们之间的空间大小来决定它们之间的关系.没有间距,用户将很难浏览页面并知道哪些内容相关而 ...

  2. css grid随页面大小_你现在可以玩下这 5 个 CSS 新功能

    在浏览器开始实现它们之前,CSS 新的功能通常需要经过长时间讨论之后,才在W3联盟的规范中定义.有许多值得一提的 CSS 新功能,但是在本文中,我们重点介绍可以浏览器的稳定版中进行测试的五个功能: C ...

  3. 熟悉html css,编写HTML和CSS的前端开发中不一定熟悉JavaScript

    原标题:编写HTML和CSS的前端开发中不一定熟悉JavaScript 作为前端开发人员,HTML.css.Java是必备的知识技能,但是现实工作工作中并非所有的前端都知道Java,根据外国一个网站的 ...

  4. 表单html遇到的问题及处理,Web前端开发中常见问题及解决方案

    Web前端开发中常见问题及解决方案 时间:2017-04-24     来源:web前端开发小赢家 作为一名web前端开发工程师,我们在工作时免不了会遇到各种各样的问题.因为web前端开发相对于Jav ...

  5. 前端开发中icon图标使用的那些门道儿

    前端开发图标使用 在日常开发,前端coder绕不开一个话题,在页面上添加各种小图标,比如 或者是这样的: 一般来说,总体上有三种方案: 位图图标,png图片,经典的使用场景--精灵图: 字体图标,比较 ...

  6. android treeview 树形结构,前端开发中,使用TreeView控件创建树形结构

    原标题:前端开发中,使用TreeView控件创建树形结构 Wijmo是一款使用Type编写的新一代Java/HTML5控件集.它秉承触控优先的设计理念,在全球率先支持AngularJS,并提供性能卓越 ...

  7. 前端开发中常用图片格式

    前端开发中常用图片格式 在我们的日常开发中.必不可少会使用很多种图片. 我们需要根据业务场景来选择所使用的图片类型. 这里我整理了一些常用图片类型.他们的优缺点以及建议的使用场景. 如何在计算机中显示 ...

  8. 前端开发中的性能那点事

     前端开发中的性能那点事(一)巧用xdebug 前言: 在我们平时的php开发中,一个大的项目经过长时间的积累以后你会发现性能越来越慢,而性能到底消耗在了什么地方,常常是一个令人头疼的问题,funct ...

  9. 初学者Web介绍一些前端开发中的基本概念用到的技术

    Web开发是比较费神的,需要掌握很多很多的东西,特别是从事前端开发的朋友,需要通十行才行.今天,本文向初学者介绍一些Web开发中的基本概念和用到的技术,从A到Z总共26项,每项对应一个概念或者技术. ...

最新文章

  1. 调试Tomcat源码
  2. 根据总用量计算每种包装规格的购买量和总价
  3. mysql 特殊字符
  4. main_loop()函数解析(1)
  5. 怎么样使用git克隆网站上的代码到本地文件夹(快捷)
  6. 如何把很多照片拼成一张照片_把很多小照片拼成一张大照片是怎么做的
  7. php 今天 明天 后天 显示10天,【微信小程序】实现含有今天,明天,后天的日期组件...
  8. 一步步创建第一个Docker App —— 4. 部署应用
  9. Linux(centOS)手动安装删除Apache+MySQL+PHP+Memcached原创无错版
  10. python 取字符串的最后一位_python中获得一个字符串最后出现位置 | 学步园
  11. 【论文】(COPRA)Finding overlapping communities in networks by label propagation
  12. iphone手机微信聊天记录恢复办法
  13. Python的index函数用法
  14. “辩”与“辨”的区别
  15. 知名爆料者:新款MacBook Air采用类似iMac的多彩设计
  16. 目标检测算法的大体框架-------backbone、head、neck
  17. python中矩阵的表示方法_在python中创建数字的二进制表示形式的矩阵 - python
  18. Python中 whl包、tar.gz包的区别
  19. bootstrap4 知识总结
  20. 光脚丫学LINQ(004):分组数据

热门文章

  1. 加快android编译速度
  2. 山东中医院大学计算机科学与技术,2021年山东中医药大学计算机科学与技术专业招生...
  3. 基于JAVA+SpringMVC+Mybatis+MYSQL的OA办公系统
  4. k8s、jenkins集成
  5. Linux 下 Shell 命令的分类及用法
  6. 将View兑换Bitmap
  7. 由浅入深理解索引的实现(2)【转】
  8. Silverlight 信息显示与编辑控件 示例
  9. android 菜单隐藏了,隐藏一些导航菜单菜单项 – Android
  10. iis php.exe,在IIS75下使用php运行exe程序的总结