Html 是否可以在不使用 <fieldset> 标签的情况下实现类似 <fieldset> 的效果?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2213881/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 02:07:47  来源:igfitidea点击:

Is it possible to achieve a <fieldset>-like effect without using the <fieldset> tag?

htmlcssfieldset

提问by zneak

I personally like the <fieldset>tag because of how it draws a box and puts the <legend>at the top of it, over the border. Like this.

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

example image of what I'm trying to achieve

我要实现的目标的示例图像

However, the fieldsetelement was made to organize forms, and using it for general design is no better than using tables for general design. So, my question is... how can I achieve the same result using another tag?The border has to be erased under the <legend>(or whatever other tag will be used), and since there could be a "complex" body background image, I can't afford to just set the background-colorof the legend to match the one of the element under.

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

I'd like it to work without JavaScript, but CSS3 and XML-based formats (such as SVG or XHTML) are fine.

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

采纳答案by mercator

No, it isn't really possible. Even browser makers themselves are struggling with that.

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

Of course, I couldn't resist having a go at it anyway. And I spent so much time on that, that Anonymouscame up with a "solution" rather similar to mine in the mean time (his test1). But mine doesn't need the fixed width "legend".

当然,无论如何我还是忍不住要试一试。我花了很多时间,匿名提出了一个“解决方案”,同时与我的(他的test1)非常相似。但我的不需要固定宽度的“图例”。

This code is evidently a bit of a hack, though, and I don't know how well it'll fare in complex sites. I also agree with Anonymous that using a fieldset for grouping isn't nearly as bad as using tables for layout. Fieldsets were designedfor grouping elements, though in HTML they're really only supposed to be used for grouping form controls.

不过,这段代码显然有点小技巧,而且我不知道它在复杂站点中的表现如何。我也同意 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>

As a side note, you might also want to have a look at the HTML5 figureand figcaptionelements. Those seem to be the best elements to use in your example.

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

That's only for the semantic part of the issue, though, since I don't think those elements are rendered the same as a fieldset/legend. Not to mention that current browsers probably don't support these elements yet to begin with.

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

回答by Mathias Bynens

Demo jsBin link

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

回答by Anonymous

However, it was made to organize forms, and using it for general design is no better than using tables for general design

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

This is mistaken. The main problem with using tables for layout is that almost no layouts map to tabular data. The second problem is that none of those that don't map to tabular data are tabular data, and some of those that do aren't. That is, the semantics of the markup wouldn't match those of the page. In addition, pragmatically, tables' layout mechanism usually makes custom styling and text-only browsing painful or impossible.

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

Now, fieldset clearly has the intent of grouping form fields. And choosing an element for its appearance is almost always a sign it's a bad choice. However, for this specific example I would argue that a fieldset+legend containing a list has almost no disadvantages (in fact, the only one I can think of is a scaper which naively interprets fieldset as signalling a form and then wasting the user's time enumerating its contents differently; but I know of nothing which actually does this). The main reason for this is that the form element serves the functional and semantic purpose of containing inputs, while fieldset has possessed since the early days had special, non-reproducable visual effects. In addition, if the visual elements in the fieldset are in any way functional, semantically the fieldset does again contain a set of interactive widgets, which was the original point.

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

My advice is to use it if you want to. I wouldn't, but not because of semantic considerations: I prefer not to rely on special effects, and eschew form over function in general.

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

Anyway, here's something to chew on:

无论如何,这里有一些值得咀嚼的东西:

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

回答by untill

Here a possible solution with a focus on simplicity (if you can loose your requirement for transparent background a bit). No additional elements.

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

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>

回答by Danziger

If you need to use border-radiusas well:

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

回答by Khayri R.R. Woulfe

Use ::beforepseudoelement to generate the top border of the emulated <fieldset>, then position the emulated <legend>element over the ::beforeblock with z-indexand positionproperties. Lastly, use gradient and a solid color-stop on the top of the emulated fieldset, setting the top color of the linear gradient to transparent so whatever background is behind the fake fieldset will be visible.

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

回答by patrick

I got a reasonable result.

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

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

回答by Mickael Dubois

I update a little bit the propostion of Anonymous to that:

我更新了一点匿名的提议:

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

回答by John Leidegren

I believe you already know the answer.

相信你已经知道答案了。

You have 2 options, provide your own border (that's a lot of unnecessary work) or position an element with occludes the border (the problem with that is that you can only have a solid background color, but maybe that's fine).

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

To my knowledge there's not anything you can do to make this workout nicely in every browser out there. I like your style though, it's the right approach but probably not a problem you'll be able to solve in a satisfying manner.

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

My general opinion on these topics is that you should not try and do things with the web that requires A) excessive effort or B) a markup solution which is not entirely obvious to begin with. The web has limitations and you would do well to ad-her to them rather than trying to work around those limitations.

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

So I'm forced to ask, what's the problem with <legend/>?

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