56

我个人喜欢这个<fieldset>标签,因为它如何绘制一个框并将其放在<legend>它的顶部,越过边界。像这样。

我正在努力实现的示例图像

但是,该fieldset元素是用来组织表格的,将其用于一般设计并不比使用表格进行一般设计更好。所以,我的问题是......我怎样才能使用另一个标签来实现相同的结果?必须在 (或将使用的任何其他标签)下擦除边框<legend>,并且由于可能存在“复杂”的主体背景图像,我不能只设置background-color图例的 以匹配元素之一在下面。

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

4

9 回答 9

44

演示 jsBin 链接

.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>

于 2010-02-06T17:25:01.520 回答
27

不,这真的不可能。甚至浏览器制造商自己也在为此苦苦挣扎。

当然,无论如何,我都忍不住要试一试。我在这上面花了很多时间,以至于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>

作为旁注,您可能还想看看 HTML5figurefigcaption元素。这些似乎是您的示例中使用的最佳元素。

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

于 2010-02-06T20:53:15.867 回答
6

但是,它是用来组织表格的,用它来做一般设计并不比用表格做一般设计好

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

现在,fieldset 显然具有对表单字段进行分组的意图。选择一个元素的外观几乎总是表明这是一个糟糕的选择。但是,对于这个特定的示例,我认为包含列表的 fieldset+legend 几乎没有缺点(事实上,我能想到的唯一一个是 scaper,它天真地将 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>

于 2010-02-06T19:14:51.113 回答
3

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

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>

于 2017-12-06T12:53:02.317 回答
1

如果您还需要使用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>

于 2020-02-03T21:52:28.327 回答
0

相信你已经知道答案了。

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

据我所知,您无法做任何事情来在每个浏览器中很好地进行此锻炼。不过我喜欢你的风格,这是正确的方法,但可能不是你能够以令人满意的方式解决的问题。

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

所以我不得不问,<legend/>有什么问题?

于 2010-02-06T17:22:35.440 回答
0

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

    <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>

于 2015-05-29T00:57:17.753 回答
0

我稍微更新了 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>
于 2016-01-12T04:02:31.807 回答
0

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

于 2018-02-23T07:57:52.493 回答