在CSS中,我们有auto
值,它可以用于像margin
,position
,height
,width
等属性。在本文中,会先解释auto
的工作方式以及如何最大程度地利用auto
的技术细节,当然,会配合一些用例和示例。
简介
auto
关键字的使用因属性而异。对于本文,我将在每个属性的上下文中解释值。
width: auto
块级元素(如
或)的初始宽度是auto,这使得它们占据了包含它们的块的整个水平空间。
根据CSS规范:
‘margin-left’ + ‘border-left-width’ + ‘padding-left’ + ‘width’ +
‘padding-right’ + ‘border-right-width’ + ‘margin-right’ = 块的宽度
当一个元素的宽度值为auto时,它包含margin、padding和border,不会变得比它的父元素大。其中 content 的宽度将是content本身减去margin、padding和border。
我们以上面的模型为例。
html
<div class="wrapper">
<div class="item">
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eos maxime cum non cupiditate, perferendis saepe vitae fugiat id exercitationem officiis voluptate sint ducimus commodi reiciendis error itaque dolores ipsam? Ea!p>
div>
div>
<div class="wrapper">
<div class="item">
<p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Eos maxime cum non cupiditate, perferendis saepe vitae fugiat id exercitationem officiis voluptate sint ducimus commodi reiciendis error itaque dolores ipsam? Ea!p>
div>
div>
css
* {
box-sizing: border-box;
}
.wrapper {
max-width: 600px;
margin: 2rem auto 0;
padding: 1rem;
}
.item {
padding: 1rem;
margin: 0 50px;
border: 15px solid #1f2e17;
}
* {
box-sizing: border-box;
}
.wrapper {
max-width: 600px;
margin: 2rem auto 0;
padding: 1rem;
}
.item {
padding: 1rem;
margin: 0 50px;
border: 15px solid #1f2e17;
}
一切都好,元素 item被限制在其父项中。
是,如果我们将元素item的宽度更改为100%而不是auto会发生什么?该元素将占用其父项的100%,加上左侧和右侧的边距。
// css
.item {
width: 100%;
padding: 1rem;
margin: 0 50px;
border: 15px solid #1f2e17;
}
// css
.item {
width: 100%;
padding: 1rem;
margin: 0 50px;
border: 15px solid #1f2e17;
}
该元素的宽度为568px,是以下各项的总和:
‘border-left-width’ + ‘padding-left’ + ‘width’ + ‘padding-right’ +
‘border-right-width’ = 15 + 16 + 506 + 16 + 15 =568px
如果方向是ltr,则完全忽略margin-right。在我们的例子中,这种情况发生了。但是,如果布局是rtl,那么margin-left将被忽略。
事例源码:https://codepen.io/shadeed/pen/f305220fbd4b444371bdef11dad014ec?editors=0100
width 用例: auto
仅仅解释基础知识不足以使我们掌握这一概念,因此需要一些事例来说明。
手机和 PC 之间的宽度不同
我们有一组按钮。在移动设备上,我们希望它们彼此相邻(每个按钮包装器占据其父元素的50%),而在桌面设备上,每个按钮都应该占据其父元素的全部宽度。该怎么做?
HTML
class="group">
class="group__item">class="c-button">Sign In
class="group__item">class="c-button c-button--ghost">Register
这里使用 flex
CSS
.group {
display: flex;
}
.group__item {
width: 50%;
}
.group {
display: flex;
}
.group__item {
width: 50%;
}
对于 PC,我们每个项需要都取全宽。在这种情况下,你可能倾向于使用width: 100%,对吗?下面是一个更好的解决方案。
CSS
@media (min-width: 800px) {
/* Revert the wrapper to a block element instead of flex */
.group {
display: block;
}
.group__item {
width: auto;
}
}
@media (min-width: 800px) {
/* Revert the wrapper to a block element instead of flex */
.group {
display: block;
}
.group__item {
width: auto;
}
}
由于.group是一个块元素,因此使用width: auto可以很好地填充其父元素的可用空间。
事例源码:https://codepen.io/shadeed/pen/399de6d9d473137998f87f957cfdfa03?editors=1100
height: auto
说到height,情况就不一样了。元素的高度等于默认值为auto的内容。
考虑下面的例子
<div class="wrapper">
<div class="item">What's my height?div>
div>
<div class="wrapper">
<div class="item">What's my height?div>
div>
要使.item获得其容器的全部高度,我们可以使用以下方法之一:
给.wrapper一个固定的高度,然后为.item元素添加height: 100%
对.wrapper使用 flex 布局,默认情况下它将拉伸子项.item
CSS
.wrapper {
height: 200px;
}
.item {
height: 100%;
}
.wrapper {
height: 200px;
}
.item {
height: 100%;
}
margin 和 auto 关键字
对于margin,最常见的用例是将已知宽度的元素水平居中。
请考虑以下示例:
要让上面的蓝色矩形居中,可以使用下面的方法:
.element {
margin-left: auto;
margin-right: auto;
}
.element {
margin-left: auto;
margin-right: auto;
}
根据CSS规范:
如果margin-left和margin-right值均为auto,则它们的使用值相等。这使元素相对于包含块的边缘水平居中。
具有绝对定位元素的 margin:auto
另一个不太常见的将绝对定位元素居中的用例是margin: auto。当我们有一个元素应该在它的父元素内部水平和垂直居中时,我们可能会倾向于使用translateX或translateY。
我们可以使用下面方法让具有绝对定位元素居中:
设置的宽度和高度。
元素应具有position: absolute
HTML
class="wrapper">
class="item">I am centered.
CSS
.wrapper {
position: relative;
}
.item {
width: 200px;
height: 100px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
.wrapper {
position: relative;
}
.item {
width: 200px;
height: 100px;
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
事例源码:https://codepen.io/shadeed/pen/b086f8402be981e871ac5db15495dec8?editors=0100
Flexbox
在某些情况下,在flexbox中使用自动页边距非常有用。当一个子项目有一个margin是auto 时,它将被推到远的另一边。例如,如果一个flex项目的左边是margin-left: auto,那么它将被推到最右边。
考虑下面的模型,父级元素是一个 flex
我们想把第二项推到最右边,自动边距就派上用场了。
CSS
.wrapper {
display: flex;
}
.item-2 {
margin-left: auto;
}
.wrapper {
display: flex;
}
.item-2 {
margin-left: auto;
}
不仅如此,它还可以在水平或垂直方向工作。参见下面的示例
CSS
.item-2 {
margin-top: auto;
}
.item-2 {
margin-top: auto;
}
另外,如果只有一个子元素,则可以使用margin:auto将其水平和垂直居中。
CSS
.item-1 {
margin: auto;
}
.item-1 {
margin: auto;
}
flex 属性和 auto 关键字
在flexbox中,我们可以使用flex: auto作为子项目。这是什么意思?当一个子项目有flex: auto时,它等价于flex: 11 auto,与下面等价:
CSS
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
MDN 描述
该项目根据其宽度和高度属性调整大小,但会增长以吸收flex容器中的任何额外自由空间,并会收缩到其最小尺寸以适合该容器,这等效于设置“ flex:1 1 auto”。
具有flex:auto的项目将根据其宽度和高度来调整大小,但它可以根据可用的额外空间来增大或缩小。在研究本文之前,我不知道这一点!
HTML
class="wrapper">
class="item item-1">Item
class="item">Item
class="item">Item
CSS
.wrapper {
display: flex;
flex-wrap: wrap;
}
.item {
width: 120px;
height: 500px;
}
.item-1 {
flex: auto;
}
.wrapper {
display: flex;
flex-wrap: wrap;
}
.item {
width: 120px;
height: 500px;
}
.item-1 {
flex: auto;
}
事例源码:https://codepen.io/shadeed/pen/4914b4517b858f0fcf0f8acd07c64b1e?editors=1100
CSS grid 和自动设置一个 `auto` 列
在CSS Grid中,我们可以设置一个列为auto,这意味着它的宽度将基于它的内容长度。看看下面,你就知道我的意思了:
wrapper {
display: grid;
grid-template-columns: auto 1fr 1fr;
}
wrapper {
display: grid;
grid-template-columns: auto 1fr 1fr;
}
grid 和 auto 边距
使用CSS网格时,可以使用自动页边距实现类似于 flexbox 的结果。当我们有一个网格,并且其中的网格项目具有margin-left: auto时:该项目将被推到右边,其宽度将基于其内容长度
考虑下面的例子:
当我们希望item1的宽度基于其内容,而不是网格区域。通过使用margin-left: auto,可以通过下面代码实实现:
.item-1 {
margin-left: auto;
}
.item-1 {
margin-left: auto;
}
从右向左布局
值得一提的是,使用margin-left: auto或margin-right: auto对于从左到右的布局(例如英语)可能效果很好。但是,在多语言网站上工作时要当心颠覆这些价值观。更好的是,使用flexbox或grid属性,以防使用它们完成工作。如果没有,那么请使用自动页边距作为最后的选择,而应使用CSS逻辑属性。
overflow 属性
当我们有一个元素时,我们应该考虑它应该包含的最小和最大内容。如果内容超过了最大值,那么我们需要显示一个滚动条。
你可能想使用以下内容:
element {
overflow-y: scroll;
}
element {
overflow-y: scroll;
}
然而,这可能会显示一个滚动条,即使内容高度很短。参见下面的示例
在 Chrome 窗口中,滚动条总是显示出来,这是不正确和令人困惑的行为。
通过使用auto关键字,我们可以确保滚动条不会显示,除非内容高度大于它的容器。
根据MDN:
取决于用户代理。如果内容适合填充框内部,则它看起来与可见内容相同,但仍会建立新的块格式化上下文。如果内容溢出,桌面浏览器会提供滚动条。
.element {
overflow-y: auto;
}
.element {
overflow-y: auto;
}
position 属性
对于CSS定位属性top,right,bottom和left,我们可以使用auto关键字作为它们的值。接下来我要解释的是对我来说是新的,我在研究本文时学到了它。
考虑下面的模型:
我们有一个有内边距的 wrapper
.wrapper {
position: relative;
padding: 16px;
}
.item {
position: absolute;
width: 100px;
height: 100px;
}
.wrapper {
position: relative;
padding: 16px;
}
.item {
position: absolute;
width: 100px;
height: 100px;
}
在CSS中,每个属性都有一个初始值/默认值。如果我检查了子项并转到computed styles,你猜下left属性的值会是什么?
left的默认值为16px,即使没有设置。为什么会发生这种情况?好吧,原因是绝对定位的元素相对于其最接近的父元素具有position:relative。该父项具有padding: 16px,因此子项位于顶部和左侧的16px处。有趣,不是吗?
现在,你可能会问,这样做有什么好处?好吧,让我继续。
假设子项必须在较小的视口中位于距左侧100像素的位置,对于桌面,它应恢复为默认位置。
.wrapper {
position: relative;
}
.item {
position: absolute;
left: 100px;
width: 100px;
height: 100px;
}
.wrapper {
position: relative;
}
.item {
position: absolute;
left: 100px;
width: 100px;
height: 100px;
}
如何在较大的视口中重设left?我们不能使用left:0,因为这会将子元素粘到边缘,这不是我们想要的。请参阅下面的模型,以了解我的意思。
要以正确的方式重置子项,我们应该使用left: auto。根据 MDN:
如果元素是静态元素,则将定位在它应该水平定位的位置
这意味着,它会尊重padding,而不会将子条目粘贴到其父条目的边缘。
.item {
position: absolute;
left: 100px;
width: 100px;
height: 100px;
}
@media (min-width: 800px) {
.item {
/* This is equivalent to left: 16px */
left: auto;
}
}
.item {
position: absolute;
left: 100px;
width: 100px;
height: 100px;
}
@media (min-width: 800px) {
.item {
/* This is equivalent to left: 16px */
left: auto;
}
}
top属性也是如此。对于right和bottom属性,其默认计算值分别等于元素的宽度和高度。
事例源码:https://codepen.io/shadeed/pen/d062539938346e5458f769cbc08833e1?editors=0100
用例和示例
值得一提的是,下面的用例可能还不够,但是我尝试添加一些用例,希望它们对你们有用。
提示箭头
对于提示框,我们需要一个指向箭头,以使其对用户更加清晰。如果我们正在设计系统上,则应该考虑多个状态。例如,提示的箭头指向左侧,另一个箭头指向右侧。
.tooltip:before {
/* 箭头代码 */
position: absolute;
left: -15px;
}
/* 这是一个箭头指向右侧的版本*/
.tooltip.to-right:before {
/* 箭头代码 */
position: absolute;
left: auto;
right: -15px;
.tooltip:before {
/* 箭头代码 */
position: absolute;
left: -15px;
}
/* 这是一个箭头指向右侧的版本*/
.tooltip.to-right:before {
/* 箭头代码 */
position: absolute;
left: auto;
right: -15px;
请注意,在初始实现中,我使用left: auto来覆盖left: -15px。供您参考,这是非常常用的,我建议改用以下内容:
.tooltip:before {
position: absolute;
right: 100%;
}
.tooltip.to-right:before {
/* Arrow code */
position: absolute;
right: auto;
left: 100%;
}
.tooltip:before {
position: absolute;
right: 100%;
}
.tooltip.to-right:before {
/* Arrow code */
position: absolute;
right: auto;
left: 100%;
}
通过使用100%,我们避免了使用硬编码的值(箭头宽度),如果我们改变箭头的大小,这个值可能会失败。这是一个更经得起时间考验的解决方案。
卡片组件
你可能有一个card组件,其左上角有一个操作,它可能仅用于装饰,也可能是一个有用的操作。不管是什么,你都应该考虑到它是双向的。
通过使用left:auto,我们可以很容易地重置它的基本实现。
.card .icon {
position: absolute;
left: 15px;
top: 15px;
}
.card.is-right .icon {
left: auto;
right: 15px;
}
.card .icon {
position: absolute;
left: 15px;
top: 15px;
}
.card.is-right .icon {
left: auto;
right: 15px;
}
Flexbox 和 自动边距
当谈到flexbox时,它有无限的可能性。通过将其与自动边距相结合,我们可以构建功能强大的布局。
考虑下面的例子
我们在右侧包含一行标题,描述和一个操作按钮的行。我们希望操作按钮贴在右侧。
HTML
<div class="item">
<div class="item-group">
div>
<button class="item__action">Confirmbutton>
div>
<div class="item">
<div class="item-group">
div>
<button class="item__action">Confirmbutton>
div>
CSS
.item {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.item__action {
margin-left: auto;
}
.item {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.item__action {
margin-left: auto;
}
就是这样!通过使用margin-left: auto,将动作推到最右角。更好的是,如果您要构建多语言网站,我们可以使用CSS逻辑属性。CSS将如下所示:
.item__action {
margin-inline-start: auto;
}
.item__action {
margin-inline-start: auto;
}
CSS grid 和自动边距
在向网格项目添加边距时,它可以是固定值,百分比或自动值。我对auto更感兴趣。考虑以下:
HTML
class="input-group"><label for="">Full Namelabel>"email" name="" id="">p>
CSS
.input-group {
display: grid;
grid-template-columns: 1fr;
grid-gap: 1rem;
@media (min-width: 700px) {
grid-template-columns: 0.7fr 2fr;
}
}
.input-group {
display: grid;
grid-template-columns: 1fr;
grid-gap: 1rem;
@media (min-width: 700px) {
grid-template-columns: 0.7fr 2fr;
}
}
我想将label 与input的左边缘对齐。为此,我需要应用以下内容:
.input-group label {
margin-left: auto;
}
.input-group label {
margin-left: auto;
}
模态设计
在进行模态设计时,重要的是要考虑内容高度很大时会发生的情况。对于这种情况,我们可以使用以下代码:
.modal-body {
overflow-y: auto;
}
.modal-body {
overflow-y: auto;
}