工作中遇到的特殊CSS布局
点击上方“前端大学”,选择“星标”
前端IT干货第一时间送达!
作者:BrownBear
https://juejin.im/post/5d23380cf265da1b971a9899
日常开发中,设计师总会提出各种奇思妙想的需求,为我们的UI还原工作带来很多挑战。虽然有时确实会让我们花蛮多时间去实现,但从一方面想这也是个机会,让我们更深入了解的浏览器布局方式。本文主要记录之前工作中遇到的特殊布局,都是通过CSS方式去实现。
多条件留白布局
图中有两个内容块A和B,他们宽度取决于内容宽度,左右侧留白有max-width: 200px
限制,中间留白有min-width: 150px
限制。如果父级宽度缩小,中间留白一直保持着150px
宽度,左右侧留白宽度跟随父级宽度缩小。如下图所示:
从需求的描述来看,需要的是同时支持弹性
(宽度随父级宽度而改变)和限制条件
(max-width、min-width)的属性。一提起弹性,自然而然的就想到flex布局,只要加入占位的元素,可使用before
或after
伪类或手动插入元素,然后加上flex: 1
和限制条件即可。
在线预览:
codesandbox 地址:https://codesandbox.io/s/thirsty-dijkstra-gp5up
代码:
<style>
.container {
display: flex;
}
// 左右侧留白
.left,
.right {
flex: 1;
max-width: 200px;
}
// 中间留白
.center {
flex: 1;
min-width: 150px;
}
</style>
<div class="container">
<div class="left"></div>
<div>Content A</div>
<div class="center"></div>
<div>Content B</div>
<div class="right"></div>
</div>
中间文本截断
需求:对于文件名,在页面中一定要显示文件扩展名,非扩展名部分溢出时显示省略号。
短文件名:
长文件名:
首先需要使用JS对文件名进行裁剪,拆分出两部分:非扩展名部分和扩展名部分,放置在两个相邻的元素中。当文件名宽度 <= 父级宽度时,左侧元素和右侧元素宽度为各自内部文字宽度。当文件名宽度 > 父级宽度时,左侧元素宽度取决于内容,达到最大值后文本截断显示缩略号,右侧元素随左侧元素向右移,一直保持自身宽度不缩放。
对于这样的问题,很自然的就想到flex-shrink
。flex-shrink
用来设置当父元素的宽度小于所有子元素的宽度的和时(即子元素会超出父元素),子元素如何缩小自己的宽度。
在线预览:
codesandbox 地址:https://codesandbox.io/s/little-sound-ffc5o
代码:
<style>
.container {
display: flex;
}
.left {
flex-shrink: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.right {
white-space: nowrap;
}
</style>
<div class="row">
<span class="left">超长的文件名超长的文件名超长的文件名超长的文件名</span>
<span class="right">.jpeg</span>
</div>
这个方法有个瑕疵,就是缩略符与右侧字符存在一定空隙,不过字体小的时候不太明显。使用JS能解决这个问题,但是用JS实现需要计算字符所占宽度。因为字符的宽度不一致,不能使用字体大小*字体长度的方式,需要将字符插入一个元素,然后获取元素的宽度。对于一个长列表来说,这个方式太耗性能。权衡利弊之下,所以选择flex去实现。
竖向排列
需求:实现类似于下图中竖向排列的布局,父元素高度限定,宽度取决于子元素,子元素宽高取决于内容,子元素从上到下,从左到右排序。
一开始想着使用flex-flow: column wrap
能快速实现,但事宜愿为,顺带发现了flex布局的缺点。我给父级元素加了border,从而可以看出父元素的宽度。
设置了flex-flow: column wrap;align-content: flex-start;
后,父元素宽度仍然是百分百,但需求是宽度取决于子元素宽度,这时需要再加个display: inline-block
元素。
加了inline-block
元素后,父元素的宽度只等于一列子元素的宽度,明显不符合预期。如果不使用display: flex
,而使用display: inline-flex
呢?
一样的效果,看来flex对于此类布局还是略逊一筹,这时就需要用到很多人平时不太注意的属性wirte-mode
了。wirte-mode
属性定义了文本水平或垂直排布以及在块级元素中文本的行进方向。
MDN文档:https://developer.mozilla.org/zh-CN/docs/Web/CSS/writing-mode
效果:
在线预览:
codesandbox 地址:https://codesandbox.io/s/elegant-hill-3rm09
代码:
<style>
.list {
display: inline-block;
height: 200px;
font-size: 0;
writing-mode: vertical-lr;
}
.item {
display: inline-block;
margin: 5px 5px;
width: 150px;
height: 40px;
line-height: 40px;
border-radius: 4px;
font-size: 14px;
text-align: center;
color: #fff;
background: #00a0e9;
list-style: none;
writing-mode: horizontal-tb;
}
.item:nth-child(2),
.item:nth-child(10) {
height: 90px;
line-height: 90px;
}
</style>
<ul class="list">
<li class="item">1</li>
<li class="item">2</li>
<li class="item">3</li>
<li class="item">4</li>
<li class="item">5</li>
<li class="item">6</li>
<li class="item">7</li>
<li class="item">8</li>
<li class="item">9</li>
<li class="item">10</li>
<li class="item">11</li>
<li class="item">12</li>
</ul>
觉得本文对你有帮助?请分享给更多人!
关注「前端大学」,提升前端技能!
分享前端好文,点个 在看