css揭秘 – 结构与布局(一)

这是我参与更文挑战的第13天,活动详情查看: 更文挑战

自适应内部元素

难题

我们都知道,如果不给元素指定一个 height,它就会自适应其内容的高度,如果希望 width 也具有类似的行为,应该怎么做呢?

解决方案

css3width 定义了一些新的关键字,其中最有用的应该就是 min-content 了,这个关键字将解析为这个容器内部最大的不可断行元素的宽度(即最宽的单词、图片或具有固定宽度的盒元素),样式中的固定的 max-width 是为了给旧版的浏览器提供一个平稳的回退样式。

<figure>
  <img src="1.jpg" />
  <figcaption>
    这是一段需要跟图片的宽度对齐的文本
  </figcaption>
</figure>
<style>
  figure {
    max-width: 300px;
    max-width: min-content;
    margin: auto;
  }

  figure>img {
    max-width: inherit;
  }
</style>
复制代码

image.png

根据兄弟元素的数量设置样式

难题

在某些场景下,我们需要根据兄弟元素的总数来为它们设置样式。最常见的场景就是,当一个列表不断延长时,通过隐藏控件或压缩控件等方式来节省屏幕空间,以此提升用户体验。

解决方案

如果列表中只有一个列表项时,可以使用 :only-child 选择符来完成。

li:only-child {
    /* 只有一个列表项时的样式 */
}
复制代码

实际上,:only-child 等效于 :first-child:last-child,道理很简单:如果第一项同时也是最后一项,那从逻辑上来说它就是唯一的那一项。 :last-child 其实也是一个快捷写法,相当于 :nth-last-child(1)

li:first-child:nth-last-child(1) {
    /* 相当于li:only-child */
}
复制代码

那么,同时匹配 :first-child:nth-last-child(4) 的元素是什么呢?一个正好有四个列表项的列表中的第一个列表项,现在已经找到一种命中特定数量列表项中第一项的方法,接下来就可以用兄弟选择符( ~ )来命中它之后的所有兄弟元素:相当于在这个列表正好包含四个列表项时,命中它的每一项。

li:first-child:nth-last-child(4),
li:first-child:nth-last-child(4) ~ li {
    /* 当列表正好包含四项时,命中所有列表项 */
}
复制代码

这个方法需要的代码相当冗长繁琐,可以使用预处理器来避免这个问题。

/* 定义mixin */
@mixin n-items($n) {
    &:first-child:nth-last-child(#{$n}),
    &:first-child:nth-last-child(#{$n}) ~ & {
        @content;
    }
}
/* 调用时是这样的: */
li {
    @include n-items(4) {
        /* 属性与值写在这里 */
    }
}
复制代码

根据兄弟元素的数量范围来匹配元素

li:first-child:nth-last-child(n+4),
li:first-child:nth-last-child(n+4) ~ li {
    /* 当列表至少包含四项时,命中所有列表项 */
}

li:first-child:nth-last-child(-n+4),
li:first-child:nth-last-child(-n+4) ~ li {
    /* 当列表最多包含四项时,命中所有列表项 */
}

li:first-child:nth-last-child(n+2):nth-last-child(-n+6),
li:first-child:nth-last-child(n+2):nth-last-child(-n+6) ~ li {
    /* 当列表包含2~6项时,命中所有列表项 */
}
复制代码

满幅的背景,定宽的内容

难题

1623744933915.png

要实现如上图所示的效果,通常会准备两个元素:外层用来实现满幅的背景,内层用来显示定宽的内容,后者通过 margin:auto 实现居中的。

<footer>
    <div class="wrapper">
        <!-- 页脚的内容写在这里 -->
    </div>
</footer>
<style>
footer {
    background: #333;
}
.wrapper {
    max-width: 900px;
    margin: 1em auto;
}
</style>
复制代码

难道为了这个效果就一定要添加一层额外的元素?能否在现代 CSS 的帮助下彻底抛弃这个累赘?

解决方案

calc() 取代原先的 auto ,内层容器的样式就会变成:

.wrapper {
    max-width: 900px;
    margin: 1em calc(50% - 450px);
}
复制代码

也可以将这个长度值应用到父元素的 padding 上,整个效果是保持不变的:

footer {
    max-width: 900px;
    padding: 1em calc(50% - 450px);
    background: #333;
}
.wrapper {}
复制代码

精确控制表格列宽

难题

对于不固定的内容来说,表格的布局是很难预测的,因为列宽会根据表格的内容进行调整,即时我们显式的指定了列宽 width,也只能起到类似的作用。鉴于这个原因,我们往往不得不使用其他元素来呈现表格型数据,或者干脆接受布局效果的不可预测性。有没有什么办法可以让表格的行为更加可控呢?

解决方案

table-layout 默认值为 auto,其行为模式被称为自动表格布局算法,就是我们最熟悉的那种表格布局方式。它还有另外一个属性值 fixed,把更多的控制权交给了网页开发者。我们设置的(宽度)样式会直接起作用,而不仅仅被视为一种提示;同时,溢出行为(包括text-overflow )与其他元素行为也是一样的,因此表格的内容将只能影响表格行的高度了。

在使用时,需要对 <table> 元素或其他具有 display: table 样式的元素应用这个属性(table-layout:fixed)即可。请注意,为了确保这个技巧奏效,需要为这些表格元素指定一个宽度(哪怕是 100% )。同样,为了让 text-overflow:ellipsis 发挥作用,我们还需要为那一列指定宽度。

最后说一句

如果这篇文章对您有所帮助,或者有所启发的话,帮忙关注一下,您的支持是我坚持写作最大的动力,多谢支持。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享