【问题标题】:Is it possible to achieve a <fieldset>-like effect without using the <fieldset> tag?不使用 <fieldset> 标签是否可以实现类似 <fieldset> 的效果?
【发布时间】:2011-01-13 21:46:41
【问题描述】:

我个人喜欢&lt;fieldset&gt; 标签,因为它会绘制一个框并将&lt;legend&gt; 放在它的顶部,越过边界。像这样。

但是,fieldset 元素是用来组织 forms 的,将其用于一般设计并不比使用表格进行一般设计更好。所以,我的问题是...... 我怎样才能使用另一个标签获得相同的结果? 必须在&lt;legend&gt;(或将使用的任何其他标签)下擦除边框,因为有可能是一个“复杂”的身体背景图像,我不能只设置图例的background-color 来匹配下面的元素。

我希望它可以在没有 JavaScript 的情况下工作,但 CSS3 和基于 XML 的格式(例如 SVG 或 XHTML)也可以。

【问题讨论】:

  • 无论如何,只要使用fieldset...

标签: html css fieldset


【解决方案1】:

Demo jsBin link

.fieldset {
  border: 1px solid #ddd;
  margin-top: 1em;
  width: 500px;
}

.fieldset h1 {
  font-size: 12px;
  text-align: center;
}

.fieldset h1 span {
  display: inline;
  border: 1px solid #ddd;
  background: #fff;
  padding: 5px 10px;
  position: relative;
  top: -1.3em;
}
<div class="fieldset">
  <h1><span>Title</span></h1>
  <p>Content</p>
</div>

【讨论】:

  • 如果我想让它看起来更像我发布的示例怎么办?
  • 哦,我刚刚注意到 OP 发布了这个:“因为可能有一个‘复杂’的身体背景图像,我不能只设置图例的背景颜色来匹配下面的元素之一。”这就是我在这个例子中所做的。我看不出它会如何工作……
  • 正如您所指出的,我正在寻找 &lt;fieldset&gt; + &lt;legend&gt; 组合的永久替代品,而不是适合特定情况的代码。我很清楚这可能没有真正的解决方案,但我认为我最好还是问一下。尽管如此,你所做的还是很酷的,并且将来可能会派上用场。这不是我想要的。
  • 所以唯一的问题是假legend的背景?我很抱歉,但我恐怕对此我无能为力。 :(
【解决方案2】:

不,这真的不可能。 Even browser makers themselves are struggling with that.

当然,无论如何我都忍不住想尝试一下。我在这上面花了很多时间,以至于Anonymous 想出了一个与我同时期非常相似的“解决方案”(他的test1)。但我的不需要固定宽度的“图例”。

不过,这段代码显然有点小题大做,我不知道它在复杂网站中的表现如何。我也同意 Anonymous 的观点,即使用字段集进行分组并不像使用表格进行布局那么糟糕。字段集设计用于对元素进行分组,尽管在 HTML 中它们实际上只应该用于对表单控件进行分组。

.fieldset {
  border: 2px groove threedface;
  border-top: none;
  padding: 0.5em;
  margin: 1em 2px;
}

.fieldset>h1 {
  font: 1em normal;
  margin: -1em -0.5em 0;
}

.fieldset>h1>span {
  float: left;
}

.fieldset>h1:before {
  border-top: 2px groove threedface;
  content: ' ';
  float: left;
  margin: 0.5em 2px 0 -1px;
  width: 0.75em;
}

.fieldset>h1:after {
  border-top: 2px groove threedface;
  content: ' ';
  display: block;
  height: 1.5em;
  left: 2px;
  margin: 0 1px 0 0;
  overflow: hidden;
  position: relative;
  top: 0.5em;
}
<fieldset>
  <legend>Legend</legend> Fieldset
</fieldset>

<div class="fieldset">
  <h1><span>Legend</span></h1> Fieldset
</div>

附带说明一下,您可能还想看看 HTML5 figurefigcaption 元素。这些似乎是您的示例中使用的最佳元素。

不过,这仅针对问题的语义部分,因为我认为这些元素的呈现方式与字段集/图例不同。更不用说当前的浏览器可能还不支持这些元素。

【讨论】:

  • 不,&lt;figure&gt; 在我的情况下不会这样做,现在我想起来,&lt;fieldset&gt; 实际上没问题。但是,您的解决方案显然效果很好(尽管我会将 &lt;h1&gt; 标记更改为其他内容,因为这与我的标题模型不太匹配),非常感谢。
【解决方案3】:

但是,它是为了组织 形式,并将其用于一般设计 并不比使用表格更好 总体设计

这是错误的。使用表格进行布局的主要问题是几乎没有布局映射到表格数据。第二个问题是那些不映射到表格数据的都不是表格数据,而有些则不是。也就是说,标记的语义与页面的语义不匹配。此外,务实地讲,表格的布局机制通常会使自定义样式和纯文本浏览变得痛苦或不可能。

现在,fieldset 显然具有对表单字段进行分组的意图。选择一个元素的外观几乎总是表明这是一个糟糕的选择。但是,对于这个特定示例,我认为包含列表的 fieldset+legend 几乎没有缺点(事实上,我能想到的唯一一个是 scaper,它天真地将 fieldset 解释为发送表单,然后浪费用户的时间枚举它的内容不同;但我不知道实际上是这样做的)。主要原因是表单元素服务于包含输入的功能和语义目的,而字段集从早期就拥有了特殊的、不可重现的视觉效果。此外,如果 fieldset 中的可视元素在任何方面都具有功能性,那么从语义上讲,fieldset 确实再次包含一组交互式小部件,这就是原始点。

如果你愿意,我的建议是使用它。我不会,但不是因为语义上的考虑:我更喜欢不依赖特殊效果,并且通常避开形式而不是功能。

不管怎样,这里有一些值得细细琢磨的东西:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head><title>test</title><style type="text/css">

.fake_fieldset {
	border: 2px groove ButtonFace;
	border-top-width: 0;
	margin-left: 2px;
	margin-right: 2px;
	padding: .35em .625em .75em;
	margin-top: 1em;
	position: relative;
}

.fake_legend {
	margin-top: -1em;
}

.fake_legend.test1::before {
	position: absolute;
	top: 0;
	left: -1px;
	border-top: 2px groove ButtonFace;
	content: " ";
	width: 0.5em;
}

.fake_legend.test1::after {
	position: absolute;
	top: 0;
	right: -1px;
	border-top: 2px groove ButtonFace;
	content: " ";
	width: 80%;
}


.fake_fieldset.test2 {
	padding: 0;
	padding-top: 1px; /* no collapsed margin */
}

.fake_fieldset.test2 .fake_fieldset.container {
	margin: 0;
	border: 0;
}

.fake_legend.test2 {
	display: table;
	width: 100%;
}

.fake_legend.test2 span {
	display: table-cell;
}

.fake_legend.test2 span:first-child {
	width: 0.5em;
}
.fake_legend.test2 span:first-child + span {
	width: 0; /* cells stretch */
}
.fake_legend.test2 span:first-child,
.fake_legend.test2 span:last-child {
	/* the rest of this code is left as an exercise for the reader */
}


</style></head><body>

<fieldset><legend>foo</legend>bar</fieldset>

<div class="fake_fieldset test1"><div class="fake_legend test1">foo</div>bar</div>

<div class="fake_fieldset test2"><div class="fake_legend test2"><span></span><span>foo</span><span></span></div><div class="fake_fieldset container">bar</div></div>

</body></html>

【讨论】:

  • 您的test1 非常接近我的要求;然而,在 Firefox 和昨天的夜间 Webkit 构建下,图例单元格不知何故具有固定宽度。所以我不能真正使用它,但是您关于 &lt;fieldset&gt; 用法的 cmets 再次给了我希望,所以我可能会继续使用它们,因为它们确实包含交互式小部件。
【解决方案4】:

这是一个可能的解决方案,侧重于简单性(如果您可以稍微放宽对透明背景的要求)。没有额外的元素。

section {
  border: 2px groove threedface;
  padding: 1em;
}

section h2 {
  float: left;
  margin: -1.7em 0 0;
  padding: 0 .5em;
  background: #fff;
  font-size: 1em;
  font-weight: normal;
}
<section id=foo>
  <h2>
    Foo
  </h2>
  bar
</section>

【讨论】:

  • 这个答案简直完美!非常感谢
【解决方案5】:

如果您还需要使用border-radius

body {
  font-family: monospace;
}

.not-a-fieldset {
  border: 3px solid blue;
  border-top: none;
  padding: 0 16px 16px;
  margin: 28px 0 0;
  border-radius: 4px;
}

.not-a-legend {
  font-size: 20px;
  margin: 0 -19px;
  overflow: hidden;
  transform: translate(0, -13px);
}

.not-a-legend > span {
  float: left;
  padding: 0 8px;
  line-height: 24px;
}

.not-a-legend::before,
.not-a-legend::after {
  content: '';
  height: 8px;
}

.not-a-legend::before {
  border-top: 3px solid blue;
  border-left: 3px solid blue;
  border-top-left-radius: 4px;
  float: left;
  margin: 10px 0 0;
  width: 8px;
}

.not-a-legend::after {
  border-top: 3px solid blue;
  border-right: 3px solid blue;
  border-top-right-radius: 4px;
  position: relative;
  display: block;
  left: 0;
  top: 10px;
  overflow: hidden;
}
<section class="not-a-fieldset">
  <h1 class="not-a-legend">
    <span>Legend</span>
  </h1>
  
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</section>

【讨论】:

    【解决方案6】:

    相信你已经知道答案了。

    您有 2 个选项,提供自己的边框(这是很多不必要的工作)或定位一个遮挡边框的元素(问题是您只能有纯色背景色,但也许没关系)。

    据我所知,您无法在所有浏览器中很好地完成这项锻炼。不过我喜欢你的风格,这是正确的方法,但可能不是你能够以令人满意的方式解决的问题。

    我对这些主题的一般看法是,您不应该尝试在网络上做需要 A) 过度努力或 B) 开始时并不完全明显的标记解决方案。网络有限制,您最好将其加入其中,而不是试图绕过这些限制。

    所以我不得不问,有什么问题?

    【讨论】:

    • 我想重点是,将fieldset 用于 显示目的在语义上是不正确的,尤其是在不涉及表单字段的情况下。
    • 问题在于它在语义上是错误的。但是,查看渲染,它是完美的。有点像&lt;table&gt; 设计:它在每个浏览器上都能完美运行,但表格不是布局工具。我只是想知道是否有一些我不知道的神奇标签或 CSS 属性。
    • 我认为担心语义纯度是一种应该有合理限制的做法。这不像上帝自己下令使用(甚至名称!)“fieldset”标签。浏览器实现了一种特殊的(并且有些奇怪的)布局效果,而这种效果在其他情况下是无法获得的,这一事实是历史性的意外。
    【解决方案7】:

    我得到了一个合理的结果。

        <div>
          <div style='position:absolute;float:top;background-image: url("whiteSquare.jpg");height:20px;z-index:10;font-size:20px'>
                Header
            </div>
            
             <div style='position:absolute;float:top;border:1px dashed gray;width:300px;margin-top:12px;z-index:1'>
                 <div style='margin-top:20px;'>
                 <table>
                  <tr>
                      <td>A</td>
                      <td>B</td>
                     </tr>
                     <tr>
                      <td>A</td>
                      <td>B</td>
                     </tr>
                 </table>
                 </div>
            </div>
        </div>

    【讨论】:

      【解决方案8】:

      我稍微更新了 Anonymous 的提议:

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
      <html><head><title>test</title><style type="text/css">
      
      .fake_fieldset {
          border: 2px groove ButtonFace;
          border-top-width: 0;
          margin-left: 2px;
          margin-right: 2px;
          padding: .35em .625em .75em;
          margin-top: 1em;
          position: relative;
      }
      
      .fake_legend {
          margin-top: -1em;
      }
      
      .fake_legend.test1::before {
          position: absolute;
          top: 0;
          left: -1px;
          border-top: 2px groove ButtonFace;
          content: " ";
          width: 0.5em;
      }
      
      .fake_legend.test1::after {
          position: absolute;
          top: 0;
          right: -1px;
          border-top: 2px groove ButtonFace;
          content: " ";
          width: 80%;
      }
      .fake_legend.test1 div {
          z-index: 100;
          background: white;
          position: relative;
          float: left;
      }
      
      
      .fake_fieldset.test2 {
          padding: 0;
          padding-top: 1px; /* no collapsed margin */
      }
      
      .fake_fieldset.test2 .fake_fieldset.container {
          margin: 0;
          border: 0;
      }
      
      .fake_legend.test2 {
          display: table;
          width: 100%;
      }
      
      .fake_legend.test2 span {
          display: table-cell;
      }
      
      .fake_legend.test2 span:first-child {
          width: 0.5em;
      }
      .fake_legend.test2 span:first-child + span {
          width: 0; /* cells stretch */
      }
      .fake_legend.test2 span:first-child,
      .fake_legend.test2 span:last-child {
          /* the rest of this code is left as an exercise for the reader */
      }
      </style></head><body>
      
      <fieldset><legend>foo</legend>bar</fieldset>
      
      <div class="fake_fieldset test1"><div class="fake_legend test1">foo</div>bar</div>
      
      <div class="fake_fieldset test2"><div class="fake_legend test2"><span></span><span>foo</span><span></span></div><div class="fake_fieldset container">bar</div></div>
      
      </body></html>
      

      【讨论】:

        【解决方案9】:

        使用::before 伪元素生成模拟&lt;fieldset&gt; 的上边框,然后将模拟&lt;legend&gt; 元素定位在具有z-indexposition 属性的::before 块上。最后,在模拟字段集的顶部使用渐变和纯色停止,将线性渐变的顶部颜色设置为透明,以便可以看到假字段集后面的任何背景。

        【讨论】:

          猜你喜欢
          • 2012-04-06
          • 2017-01-01
          • 1970-01-01
          • 2011-01-21
          • 2011-09-25
          • 2023-03-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多