css样式diaplay:"contents"的妙用

本文适合了解到display:"contents"属性的功能,不知道使用场景和用途的人,因为属性比较新又很冷门。

前言(或者叫废话)

初次见到这个属性是在使用svelte时,index.html模板里,因为冷门和好奇询问AI,说是为了防注入什么的,MDN的描述是也是让人一头雾水,完全想不到有什么用途,直到一个一直困扰我多时的问题,关于shadcn组件库。

MDN:这些元素自身不会产生特定的盒子。它们被伪盒子(pseudo-box)和子盒子取代。

shadcn是一个下载到项目本地的ui组件,不同于过往的npm包组件库(......算了你们应该不爱听,svelte5没什么好用的npm组件库,我是被迫使用的,svelte在国内也很冷门,应该没人感同身受------国内大家更偏爱vue或是react)。

总之我在使用shadcn时遇到一个问题,Dialog组件结构是这样的:

html 复制代码
<Dialog.Root>
 <Dialog.Trigger>Open</Dialog.Trigger>
 <Dialog.Content>
  <Dialog.Header>
   <Dialog.Title>Are you sure absolutely sure?</Dialog.Title>
   <Dialog.Description>
    This action cannot be undone. This will permanently delete your account
    and remove your data from our servers.
   </Dialog.Description>
  </Dialog.Header>
   dialog body
  <Dialog.Footer>
    <Button>yes</Button>
    <Button>no</Button>
  </Dialog.Footer>
 </Dialog.Content>
</Dialog.Root>

Content里有Header和Footer,如果把表单放在Dialog里,表单字段在Content,提交按钮在Footer,还有一个表单标题在Header。如果把form元素直接放在Content>form,form会包裹Header和Footer,让Content布局实效。而一般组件会提供插槽让Content样式属性全部转移给form(通过snippet child),而这个Content组件并没有提供child只有children(children相当于vue的插槽slot,svelte4也是slot,svelte5改了)。如果不想破坏布局,给form手写样式,就无法让form包裹Footer的submit按钮,只能通过给form设置id,submit设置form属性和form元素关联(讨厌配置id关联)。 在认识display:contents 3个月后的现在,刚刚攻克完使用sveltekit-superforms,创建和编辑复用同一个弹窗表单组件后,突然茅塞顿开......

正文

不善言词,代码说话。vue上手简单国内基数大,用以举例。

场景一:保留功能,样式透传

给元素设置contents属性,只会让盒子模型不生效,但是html标签还在,功能也还在,比如form, 正如前言中提到shadcn弹窗组件和表单的问题。

html 复制代码
<!--shadcn-vue -->
<Dialog>
    <DialogTrigger>Open</DialogTrigger>
    <DialogContent>
      <!-- 重点 -->
      <form action="/api/submit" method="POST" style="display: contents">
        <DialogHeader>...</DialogHeader>
        <Field>
          <FiledLabel>...</FieldLabel>
          <Input name="..." />
        </Field>
        <DialogFooter>
          <Button type="reset">reset</Button>
          <Button type="submit">submit</Button>
        </DialogFooter>
      </form>
    </DialogContent>
</Dialog>

以上,DialogContent布局会忽略form直接作用于Header和Footer,好似form不存在,但是form的功能是完全保留的。

场景二:自身消失子元素节点保留

使用vue时,遇到过这样的需求(原场景忘记了):

html 复制代码
<main>
  <div role="layout" class="layout">
    <button>handle</button>
  </div>
</main>

让div消失,button还要,通常想到的vue指令v-show或者v-if:

js 复制代码
<main>
  <div v-if="isShow" role="layout" class="layout">
    <button>handle</button>
  </div>
  <button v-else>handle</button>
</main>

v-show或者v-if(display:none和设置元素hidden属性)都会让子节点也消失在页面,需要写两遍handle,如果子节点比较复杂还要提取出组件,可能还要涉及组件数据传递,代码洁癖的我难受一批。使用contents的话就容易了:

js 复制代码
<main>
  <div role="layout" class="layout" :style="{display:isShow ? 'block' : 'contents'}">
    <button>handle</button>
  </div>
</main>

场景三

交给你们了,欢迎评论区补充......

结语

现在表单验证和提交都用js完成,谁还用难用的原生form那套🤡。主要是我用过svelte已经回不去vue了,svelte的理念就是使用原生功能去实现,需要扎实的原生html css js知识,会原生就会svelte,相比vue和reeact这俩简直是魔法。正如渡一袁老师说的:

世界上最恐怖的事情是什么,就是不知道自己不知道。

vue的魔法让小白可以在原生开发比较薄弱的情况下,忽略实现细节或让事情更简单。

那为什么还去用svelte不用vue?起初看了B站峰华的《2分钟了解 Svelte,与 Vue 类似的前端框架》,可以不用被ref的value恶心,等入门了后才发现最新svelte5已经更新的面目全非......为什么drizzle流行基本占领了node的orm,他的理念不也是会sql就会drizzle吗,少些魔法。反正深入体验svelte后已经会不去vue了。

相关推荐
钱栈up10 小时前
前端改了三页、后端也动了,用户说「完全没变化」——我在 116 库上找到的三个真凶
css·数据库
燕落南枝15 小时前
CSS 字体样式:颜色、字体族、倾斜、加粗与装饰
前端·css
狮子座的男孩19 小时前
html+css基础:24、2D变换(位移/缩放/旋转/扭曲(了解)/多重变换/变换原点)
前端·css·经验分享·html·2d位移·原点变换·缩放/旋转/扭曲
子兮曰1 天前
CSS 复现 23 种设计风格:从拟物到液态玻璃的成本阶梯与兜底写法【实战】
前端·css·视觉设计
燕落南枝2 天前
CSS 学习:类型选择器与 AI 注释实战
css·人工智能·学习
燕落南枝2 天前
CSS 类选择器详解:从入门到实战
前端·css
iCxhust3 天前
模型:500kW飞轮 10kV输电线路 油田抽油机 同时考虑无功补偿 统计:全年节电量 结果56万度电
前端·css·css3·电力·飞轮
燕落南枝3 天前
CSS 后代选择器与子代选择器:从入门到实战
前端·css
王大师王文峰4 天前
HTML 入门到进阶:语义化标签、表单与多媒体一篇打通【语义化布局、表单校验、video/audio、Canvas、无障碍与 SEO】
前端·css·node.js·html·css3·jquery·html5
晓得迷路了5 天前
栗子前端技术周刊第 150 期 - Stack Overflow 开发者调查结果、TanStack Start 1.0...
javascript·css·后端