Можно ли добиться эффекта, подобного <fieldset>, без использования тега <fieldset>? - PullRequest
49 голосов
/ 06 февраля 2010

Мне лично нравится тег <fieldset> из-за того, как он рисует прямоугольник и помещает <legend> вверху над границей. Вот так.

example image of what I'm trying to achieve

Однако элемент fieldset был создан для организации форм , и его использование для общего дизайна ничем не лучше, чем использование таблиц для общего дизайна. Итак, мой вопрос ... как я могу добиться того же результата, используя другой тег? Границу необходимо стереть под <legend> (или любым другим тегом, который будет использоваться), и поскольку быть "сложным" фоновым изображением тела, я не могу позволить себе просто установить background-color легенды так, чтобы он соответствовал элементу из *. 1019 *

Я бы хотел, чтобы он работал без JavaScript, но форматы на основе CSS3 и XML (такие как SVG или XHTML) хороши.

Ответы [ 8 ]

45 голосов
/ 06 февраля 2010

Демонстрационная ссылка 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>
18 голосов
/ 06 февраля 2010

Нет, это не совсем возможно. Даже сами производители браузеров борются с этим.

Конечно, я все равно не устоял. И я потратил на это столько времени, что 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 figure и figcaption. Это, кажется, лучшие элементы для использования в вашем примере.

Это только для семантической части проблемы, так как я не думаю, что эти элементы отображаются так же, как fieldset / legend. Не говоря уже о том, что современные браузеры, вероятно, еще не поддерживают эти элементы.

6 голосов
/ 06 февраля 2010

Однако это было сделано для организации формы, и использовать его для общего дизайна не лучше, чем использовать таблицы для общий дизайн

Это ошибка. Основная проблема с использованием таблиц для макета состоит в том, что макеты почти не отображаются в табличных данных. Вторая проблема заключается в том, что ни один из тех, которые не отображаются в табличные данные, является табличными данными, а некоторые из них не являются. То есть семантика разметки не совпадает с семантикой страницы. Кроме того, прагматично, механизм компоновки таблиц обычно делает пользовательские стили и просмотр текста только болезненными или невозможными.

Теперь fieldset явно имеет намерение группировать поля формы. И выбор элемента для его внешнего вида почти всегда является признаком плохого выбора. Тем не менее, для этого конкретного примера я бы сказал, что легенда fieldset +, содержащая список, практически не имеет недостатков (на самом деле, единственное, о чем я могу подумать, это scaper, который наивно интерпретирует 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>
1 голос
/ 06 декабря 2017

Здесь возможное решение с упором на простоту (если вы можете немного потерять требование прозрачного фона). Никаких дополнительных элементов.

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>
0 голосов
/ 23 февраля 2018

Используйте псевдоэлемент ::before для создания верхней границы эмулируемого <fieldset>, затем расположите эмулируемый элемент <legend> над блоком ::before со свойствами z-index и position. Наконец, используйте градиент и однотонный ограничитель в верхней части эмулируемого набора полей, установив прозрачный верхний цвет линейного градиента, чтобы любой фон, находящийся за поддельным набором полей, был виден.

0 голосов
/ 12 января 2016

Я немного обновляю предложение 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>
0 голосов
/ 29 мая 2015

Я получил разумный результат.

    <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>
0 голосов
/ 06 февраля 2010

Полагаю, вы уже знаете ответ.

У вас есть 2 варианта: предоставить собственную границу (это много ненужной работы) или расположить элемент с окантовкой (проблема в том, что вы можете иметь только сплошной цвет фона, но, возможно, это нормально).

Насколько мне известно, вы ничего не можете сделать, чтобы сделать эту тренировку приятной в любом браузере. Мне нравится ваш стиль, хотя это правильный подход, но, вероятно, это не та проблема, которую вы сможете решить удовлетворительным образом.

Мое общее мнение по этим темам состоит в том, что вы не должны пытаться делать что-то с сетью, что требует A) чрезмерных усилий или B) решения разметки, которое не совсем очевидно с самого начала. В Интернете есть ограничения, и вы бы лучше их рекламировали, чем пытались обойти эти ограничения.

Так что я вынужден спросить, в чем проблема с

?
...