【问题标题】:Is there a way to select the first/last non-hidden element using CSS3?有没有办法使用 CSS3 选择第一个/最后一个非隐藏元素?
【发布时间】:2021-04-16 03:53:42
【问题描述】:

我想用边距设置表单字段集的样式,但删除第一个非隐藏字段集的 margin-top 和最后一个非隐藏字段集的 margin-bottom(任何字段集都可能被脚本动态设置为隐藏)。我尝试了以下 CSS 没有运气(fs2 预计没有 margin-top 但实际上有;fs3 预计没有 margin-bottom 但实际上有)。有没有办法使用 CSS3 做这样的事情?

form > fieldset {
  margin: .5em;
}

/* this doesn't work */
form > fieldset:not([hidden]):first-of-type {
  margin-top: 0;
}

/* this doesn't work */
form > fieldset:not([hidden]):last-of-type {
  margin-bottom: 0;
}
<form>
  <fieldset hidden>fs1</fieldset>
  <fieldset>fs2</fieldset>
  <fieldset>fs3</fieldset>
  <fieldset hidden>fs4</fieldset>
</form>

【问题讨论】:

  • 您打算启用边框折叠功能吗?
  • 你的意思是边距折叠?我确实有这个想法,但想要一个这种情况的通用解决方案,而不必指望保证金崩溃。
  • 最后一个这样的元素没有基于选择器的解决方案。对于第一个这样的元素,一个健壮的解决方案涉及多个选择器和多个 CSS 规则,如果不利用边距折叠,它甚至不是完全万无一失的。这应该通过 fieldset:nth-child(1 of :not([hidden])) 和 fieldset:nth-last-child(1 of :not([hidden])) 来解决,但仍然没有得到广泛支持。
  • :last-of-type 伪类根据您的选择器查找其类型的最后一个元素以及是否隐藏该元素。您的最后一个 fieldset 元素是隐藏的,因此不会应用任何内容。选择器是全有或全无,而不是以上任何一个。

标签: html css css-selectors


【解决方案1】:

gap 是为此类用例创建的

form {
  display:grid;
  gap:0.5em;
  border:1px solid red;
  margin:10px;
}
fieldset {
  margin:0;
}
<form>
  <fieldset hidden>fs1</fieldset>
  <fieldset>fs2</fieldset>
  <fieldset>fs3</fieldset>
  <fieldset hidden>fs4</fieldset>
</form>


<form>
  <fieldset hidden>fs1</fieldset>
  <fieldset>fs2</fieldset>
  <fieldset>fs3</fieldset>
  <fieldset >fs4</fieldset>
</form>

<form>
  <fieldset hidden>fs1</fieldset>
  <fieldset hidden>fs2</fieldset>
  <fieldset>fs3</fieldset>
  <fieldset >fs4</fieldset>
</form>

<form>
  <fieldset hidden>fs1</fieldset>
  <fieldset hidden>fs2</fieldset>
  <fieldset>fs3</fieldset>
  <fieldset hidden>fs4</fieldset>
</form>

【讨论】:

  • 谢谢。不幸的是,浏览器支持很糟糕。
  • @DannyLin 呃,你确定吗? ... 甚至 IE 也支持 CSS 网格:caniuse.com/css-grid ... CSS 网格并不是什么新鲜事物,它已经存在太久了
  • @TermaniAfif 支持网格肯定不支持间隙。根据MDN,IE不支持gap属性。
  • @DannyLin 这就是你所说的可怕? IE不支持什么? ... IE(死浏览器)不支持 anything 有用的东西。
  • @DannyLin 使用旧语法grid-row-gap
【解决方案2】:

您可以使用adjacent sibling selector+ 来执行此操作:

form > fieldset[hidden] + fieldset {
  margin-top: 0;
}

这会将隐藏字段集的第一个兄弟设置为没有上边距:

form > fieldset {
  margin: .5em;
}

/* this doesn't work */
form > fieldset[hidden] + fieldset {
  margin-top: 0;
}
<form>
  <fieldset hidden>fs1</fieldset>
  <fieldset>fs2</fieldset>
  <fieldset>fs3</fieldset>
</form>

【讨论】:

  • 如果我有隐藏 fs1、非隐藏 fs2、隐藏 fs3 和非隐藏 fs4,这将是错误的。在这种情况下,fs4 会意外地移除 margin-top。
【解决方案3】:

根据其他页面样式的编写方式,一种常见的技术是仅在元素底部应用边距。

/* Remove top margin */
margin: 0 0.5em 0.5em;

但由于您似乎想要删除所有垂直边距,因此对表单的顶部和底部应用负边距可能更容易?

form > fieldset {
  margin: .5em;
}
form {
  margin: -0.5em 0;
}
<span>Lorem</span>
<form>
  <fieldset hidden>fs1</fieldset>
  <fieldset>fs2</fieldset>
  <fieldset>fs3</fieldset>
  <fieldset hidden>fs4</fieldset>
</form>
<span>Ipsum</span>

【讨论】:

    【解决方案4】:

    正如@j08691 回答的那样,相邻的兄弟选择器(+)也许可以解决问题。 您还可以使用 first-of-type 选择器来仅影响第一次出现。

    form > fieldset[hidden]:first-of-type + fieldset
    

    【讨论】:

    • 如果我有隐藏 fs1、隐藏 fs2 和非隐藏 fs3,这将是错误的。在这种情况下,fs3 将意外保留 margin-top。
    • :first-of-type 将始终选择第一个字段集。见stackoverflow.com/questions/2717480/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-16
    • 1970-01-01
    • 2018-10-08
    • 1970-01-01
    • 2020-05-30
    • 1970-01-01
    相关资源
    最近更新 更多