◆

Windi CSS 其他工具类:定位、层级与 object-fit

2023-02-02 01:370
简写对应属性
z-3z-index: 3
-z-1z-index: -1
object-[left right top bottom lt lb rt rb]object-position
object-[contain cover fill none scale-down]object-fit
clear-[right left both none]clear: both
float-[right left none]float: right
static fixed absolute relative stickyposition: static

定位相关的配套工具类

position 光有定位类型不够用,还得配偏移。Windi 的偏移类是 inset 系列:

<!-- 四边全 0,等于铺满父容器 -->
<div class="absolute inset-0"></div>
<!-- 水平方向 0(left + right) -->
<div class="absolute inset-x-0 top-0"></div>
<!-- 单边 -->
<div class="absolute top-2 right-4 bottom-0 left-1/2"></div>
<!-- 负值加前导减号 -->
<div class="absolute -top-2 -left-1"></div>
<!-- auto 用来抵消继承的偏移 -->
<div class="absolute top-auto bottom-0"></div>

数值走的是间距 scale(1 = 0.25rem),也支持分数(1/2、1/3、2/3、full)转成百分比。分数在做水平/垂直居中时很常用:

<!-- 经典的绝对定位居中 -->
<div class="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
  居中
</div>

z-index 的取值范围

Windi 默认只提供 z-0 z-10 z-20 z-30 z-40 z-50 z-auto 这几档,不是任意整数。上面表格里的 z-3 和 -z-1 能用,是因为 Windi 的动态取值能力——它会在编译时解析任意数字并生成对应规则,这是它相比早期 Tailwind 的一个特色。写 z-999 也会生成 z-index: 999。

不过依赖这个能力有个副作用:类名里的数字直接暴露了魔法值,代码里散落 z-999、z-9999 之后层级关系就没人说得清了。我更倾向在配置里定义语义化的档位:

// windi.config.ts
export default {
  theme: {
    extend: {
      zIndex: {
        dropdown: '1000',
        sticky: '1020',
        modal: '1050',
        popover: '1070',
        tooltip: '1080',
      },
    },
  },
};

之后写 z-modal、z-tooltip,层级顺序一眼可读。

另外要记住 z-index 只对定位元素和 flex/grid 子项生效。给一个 position: static 的元素写 z-50 完全没有作用,这是我见过最多的「z-index 不生效」原因。Windi 不会帮你补 relative,得自己写上:

<!-- 无效 -->
<div class="z-50">...</div>
<!-- 有效 -->
<div class="relative z-50">...</div>

object-fit 与 object-position

这两个只对替换元素生效,也就是 <img>、<video>、<iframe>、<object> 这些。给 <div> 写 object-cover 没有任何效果,这一点和 background-size: cover 容易混。

前提是元素得有确定的宽高,object-fit 描述的是「内容如何填充这个已确定的盒子」:

<!-- 裁切填满,保持比例(最常用,做头像和封面图) -->
<img class="h-40 w-40 object-cover" src="..." />
<!-- 完整显示,保持比例,可能留白 -->
<img class="h-40 w-40 object-contain" src="..." />
<!-- 拉伸填满,不保持比例(默认行为) -->
<img class="h-40 w-40 object-fill" src="..." />
<!-- 原始尺寸,超出裁掉 -->
<img class="h-40 w-40 object-none" src="..." />
<!-- 取 none 和 contain 中较小的那个,不会放大小图 -->
<img class="h-40 w-40 object-scale-down" src="..." />

object-position 决定裁切时保留哪一部分,配 object-cover 用。人像封面用 object-top 能避免把脸裁掉:

<img class="h-40 w-full object-cover object-top" src="..." />

表格里的 lt / lb / rt / rb 是 Windi 的简写,对应 left-top、left-bottom、right-top、right-bottom。Windi 有不少这类缩写别名(比如 p 对 padding、m 对 margin),是它相比 Tailwind 更省字符的地方,但换到 Tailwind 就得写全称。

float 与 clear

这两个属性在 flex / grid 普及后基本只剩一个用途:文字环绕图片。

<div>
  <img class="float-left mr-4 mb-2 w-32" src="..." />
  <p>这段文字会环绕在图片右侧和下方……</p>
  <div class="clear-both"></div>
</div>

不做文字环绕的话,两栏布局用 flex 或 grid,不要用 float。

Windi 里清除浮动除了 clear-both,更推荐用 clearfix 这个内置工具类,它生成的是 ::after 伪元素方案,不需要额外的空 div:

<div class="clearfix">
  <img class="float-left" src="..." />
</div>

另一个办法是给父容器加 overflow-hidden 或 flow-root(display: flow-root 会创建新的块级格式化上下文,专为这个场景设计,副作用比 overflow-hidden 小)。

sticky 的两个前提

sticky 是最容易「配了没反应」的定位方式,因为它有两个硬前提:

  1. 必须指定至少一个方向的偏移。只写 sticky 不写 top-0 完全等同于 relative。
  2. 父容器不能有 overflow: hidden / auto / scroll。任何一层祖先设了这些值,粘性定位的参照系就变成那个滚动容器,而不是视口,表现上往往就是「不粘」。
<!-- 表头吸顶 -->
<thead class="sticky top-0 z-10 bg-white">...</thead>

第二条尤其隐蔽,因为 overflow-hidden 常常是为了清浮动或者裁圆角随手加上的,跟粘性定位看着毫无关系。排查时从目标元素往上逐级查 overflow 是最快的路子。

另外 sticky 元素的粘性范围被限制在父容器内,父容器滚出视口它就跟着走。想让它在整页范围内吸顶,父容器就得是那个长内容的直接祖先。

💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVEWindi CSS 其他工具类:定位、层级与 object-fit加载中