第二十九讲:帖子子元素布局技巧(二)
父元素相对定位+子元素绝对定位 的方式对于做音画帖来说几乎可以满足布局需求,但这不等于说我们可以不学其他的定位知识和技巧。实际上,CSS3+HTML5这些年来陆续推出很多新特性,基于网页布局的元素定位,有很多新奇的技巧一经发布便很快得到各大浏览器的支持,比如现在业已成为布局标准的 flex 和 grid 布局,它们都是基于 display 定位层面的。我们先来看看grid布局,这是当下最为经典的网格布局,它是一个庞大而细节丰富的系统,不过我们只用到它的一点点功能。例如以下例子,我们使用 grid 布局+特定属性 主动约束子元素的定位:
<style>
/* 父元素使用网格定位类型的display属性 */
.ma {
display: grid; /* 网格布局 */
place-items: center start; /* 放置子元素属性 y=center, x=start */
width: 600px;
height: 200px;
border: 1px solid gray;
}
/* 子元素继承display属性值 用于约束自己的子元素 */
.son {
display: inherit; /* 继承网格布局 */
place-items: center; /* 单值表示 yx 方向同 */
width: 200px;
height: 100px;
background-color: gray;
}
</style>
<div class="ma">
<div class="son">子元素</div>
</div>
点击查看效果
上例,父元素使用了grid网格布局,该布局有一个属性 place-items 放置项目,其值分xy两个方向,单值时xy方向一样定位,双值时是按 {y,x} 的次序规范子元素的定位,例如上例的 .ma 选择器中,place-items: center start; 表示,纵向子元素居中,横向居左;再如,place-items: end end; 表示子元素纵向居下,横向居右。place-items 是放置元素的意思,用于约束子元素的定位,共三个关键字值,start 开始,即横左、竖上,center 中心,end 末尾,即横右、竖下。请再回头看看代码,子元素也使用了grid网格布局,display 属性值是 inherit,继承,即继承父元素的相同属性值;place-items 属性则用了单值 center 居中,xy方向都居中,这叫绝对居中;子元素设置这样的样式,是想让它的子元素——本例中的文本——绝对居中,其效果正是如此。居中在很多场合会用到,比如从中心出发的不同大小的粒子,使用 grid 布局技术可以大大简化设置工作;再比如LRC歌词同步中的歌词展示,我们希望它能水平居中,但由于歌词长短不一,处理起来比较麻烦,而grid布局能够很好解决这个问题,只需歌词父元素设置 grid 布局加上相应的 place-items 属性设置即可。
再看如下例子:父元素使用grid布局约束子元素绝对居中,单击子元素它会发生宽高的随机变化,但不论其如何变,它都永远绝对居中:
<style>
.ma1 {
display: grid;
place-items: center;
width: 600px;
height: 200px;
border: 1px solid;
}
#son {
display: inherit;
place-items: inherit;
width: 100px;
height: 100px;
background-color: silver;
user-select: none;
}
</style>
<div class="ma1">
<div id="son">点我</div>
</div>
<script>
/* 子元素点击事件 : 随机改变自身宽高 */
son.onclick = () => {
son.style.setProperty('width', `${Math.floor(Math.random() * 500) + 50}px`);
son.style.setProperty('height', `${Math.floor(Math.random() * 150) + 50}px`);
};
</script>
点击查看效果
接下来讲一讲 flex 布局。flex 是基于二维的弹性布局,它比 grid 更早出现,我们来看看示例:
<style>
/* 父元素使用弹性布局定位类型的display属性 */
.ma2 {
display: flex; /* 弹性布局 */
gap: 8px; /* 规定子元素间距 */
alig-items: start; /* 纵向方向定位,值还有 center 和 end */
justify-content: center; /* 水平方向定位,值还有 start 和 end */
width: 600px;
height: 200px;
border: 1px solid;
}
/* 子元素继承display属性设置 */
.sons {
display: inherit;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
width: 100px;
height: 100px;
background-color: gray;
}
</style>
<div class="ma2">
<div class="sons">子元素1</div>
<div class="sons">子元素2</div>
<div class="sons">子元素3</div>
</div>
点击查看效果
flex 弹性布局使用 justify-content 和 align-items 设置子元素的xy方向的定位,可选属性值也是 start、center 和 end 三个。这两个属性 grid 网格布局也可以使用但它有一个更简化的 place-items 属性可以做相同的工作。
以上是通过 flex 和 grid 布局,令父元素具备约束子元素基于对齐方式的具体定位的能力,主要用于网页或帖子布局。最后讲讲子元素自身的另外一种定位方法,通过 transform 属性实现。看例子加以领会:
<style>
.ma3 {
width: 600px;
height: 300px;
border: 1px solid gray;
position: relative;
}
.ball {
position: absolute;
width: 50px;
height: 50px;
background: linear-gradient(45deg, yellow, red);
border-radius: 50%;
display: grid;
place-items: center;
}
/* 1号球 :原地不动(免设置)*/
/* 2号球 :横向平移(translate单值时基于X轴) */
.ball:nth-of-type(2) { transform: translate(120px); }
/* 3号球 :纵向平移 */
.ball:nth-of-type(3) { transform: translateY(120px); }
/* 4号球 :横向+纵向平移 */
.ball:nth-of-type(4) { transform: translate(120px, 120px); }
/* 5号球 :旋转*横向平移 */
.ball:nth-of-type(5) { transform: rotate(30deg) translateX(500px); }
/* 6号球 :旋转+纵向平移 */
.ball:nth-of-type(6) { transform: rotate(-60deg) translateY(360px); }
</style>
<div class="ma3">
<div class="ball">1</div>
<div class="ball">2</div>
<div class="ball">3</div>
<div class="ball">4</div>
<div class="ball">5</div>
<div class="ball">6</div>
</div>
点击查看效果
transform 是 CSS 的 2d 或 3d 的转换或曰变形的属性,其内容涵盖了平移(translate)、旋转(rotate)、缩放(scale)、扭曲(skew)等,其中平移可以是x方向或y方向或xy方向同时移动,rotate是旋转,可正向或逆向旋转,这取值与角度的正负值。一个元素可以同时设置多个转换属性值,有趣的是,元素旋转在先平移在后,则元素会环绕中心原点即元素最初所处的中心点运动——如果运动是持续的话。关于环绕运动,从上例的5号球和6号球应该能够看得出一点端倪,而下面的例子则真正直观地展示这个特效:
<style>
.ma4 {
width: 300px;
height: 300px;
border: 1px solid gray;
display: grid; /* 使用grid布局定位子元素 */
place-items: center; /* 令子元素绝对居中 */
position: relative;
}
.son1 {
width: 50px;
height: 50px;
background: linear-gradient(45deg, olive, red);
animation: go 6s linear infinite;
}
/* 关键帧动画 :旋转+平移产生环绕运动 */
@keyframes go {
from { transform: rotate(0) translateX(125px); }
to { transform: rotate(-360deg) translateX(125px); }
}
</style>
<div class="ma4">
<div class="son1"></div>
</div>
点击查看效果
即便是运动着的元素,我们也需要能够掌控其位置,不令其越界——除非越界是我们所希望的需求。所以,上面的示例,① 使用 grid 布局令子元素绝对居中,这样子元素的运动将环绕父元素的中心点进行;② 从 0 到 360deg 的旋转刚好是一个圆周的角度,这使得子元素在自转一周的同时环绕运动也能首尾无缝衔接;③ 横向平移是 125px 而不是别的数字,是因为父元素的半径为150px、子元素半径为25px,150-25=125,父元素半径减去子元素半径是为了让子元素刚好在父元素内最大化地绕圈圈。
除此之外,还有一些其他的布局技巧,这里就不一一讨论了,相信随着做帖经验的不断丰富,大家会慢慢接触到。
作业 :参照最后的示例,做个一父三子 的小东东,父元素为圆形空心用以模拟轨道、子元素球体实心用以模拟星球。要求:三个小星球中,每一个星球有一半在轨道内、另一半再轨道外,它们彼此间间隔一定距离,最终效果是三个小星球沿着轨道你追我赶地进行有序运动。【提示】小球错开运动可在 animation 属性中使用简写形式的属性值加入延时执行动画的时间属性,整体语句结构为 animation: 动画名称 运动周期时长 运动延时 linear infinite ,后两个属性分别表示匀速运动、永不停歇。运动周期时长和运动延时均需要 s 或 ms 单位,延时支持负数值,负数值表示提前运行。
返回目录