9

You can't have two legends for a given fieldset, but is there a way to get a legend effect without using the <legend> tag?

<!-- left legend -->
<fieldset>
    <legend>
        Some Text
    </legend>
</fieldset>

I can add align=right to the legend tag to make it on the right-hand side, but again, I can't have two legends. I'd like to have a legend to the left, and something like a legend to the right. Something like the image below.

How can I accomplish this using HTML and CSS? Here's a Fiddle, I basically want to combine these two. On the left would be regular legend text, and to the right would be a dropdown if it matters.

Fieldset with 2 legends

Update

Here's some code I'm working with :

#shifter {
  position: relative;
}
#cataright {
  position: absolute;
  top: -25px;
  right: 20px;
  font-weight: bold;
}
.grey {
  padding: 15px;
  padding-left: 30px;
  padding-right: 30px;
  border: solid black 3px;
  border-radius: 7px;
  background-color: #DDDDDD;
}
<fieldset class="grey" id="shifter">
  <legend>
    Title
  </legend>
  <div id="cataright">
    Sort by
    <select id="sort" onchange="sort();">
      <option value="original">Release Date</option>
      <option value="popularity">Popularity</option>
      <option value="rating">Highest Rated</option>
    </select>
  </div>
</fieldset>
web-tiki
  • 99,765
  • 32
  • 217
  • 249
gator
  • 3,465
  • 8
  • 36
  • 76

5 Answers5

9

You can do that by adding an extra element and positioning it absolutly in the <fieldset> :

fieldset {
  position: relative;
}
.legend2 {
  position: absolute;
  top: -0.2em;
  right: 20px;
  background: #fff;
  line-height:1.2em;
}
<fieldset>
  <legend>
    Some Text
  </legend>
  <div class="legend2">Some other Text</div>
</fieldset>
web-tiki
  • 99,765
  • 32
  • 217
  • 249
  • 2
    again, without supporting (parent's) background image, everything seems to be so simple. – King King May 08 '14 at 16:53
  • 3
    I mean if the parent of the fieldset need to have some image (or gradient) background, the solid background (white) of the `legend2` will be shown up and of course it's unacceptable. It depends on the use case. Try applying the same background to the `legend2` with appropriate `background-position` may help. – King King May 08 '14 at 17:00
  • yes, that is true @riista do you have a plain background color or do you need support for a background image/gradient? – web-tiki May 08 '14 at 17:02
  • 1
    Just plain white. It really doesn't matter, I'm moreso concerned with how to do it than actually implementing it. One hurdle at a time. Thanks for the help! – gator May 08 '14 at 17:10
  • @riista ***I'm moreso concerned with how to do it than actually implementing it*** -> in fact this answer implemented it for you, if you mean you want to implement the version **supporting background**, I think it's not such easy and may have a **totally different approach**. – King King May 08 '14 at 17:20
  • Now that you mention it, it does kind of matter. After trying it out, I come across an instance where it overlaps the fieldset border. Here's an image showing what I have: http://imgur.com/nl2qrMn – gator May 08 '14 at 17:26
  • @riista in this example, it looks like you forgot to give a background-color to the second legend. But without the code it's hard to tell... – web-tiki May 08 '14 at 17:27
  • @web-tiki, the thing is I don't need or desire a background color. Inside the fieldset is a given color, but outside it's something else. I'd ideally like to cut away part of the fieldset border to accommodate the layer above it. I'll edit some code in the OP. – gator May 08 '14 at 17:28
  • @riista well with this technique, you will have to set a background color (the same as the general background-color) to the absolutely positioned element to hide the border. That is why it won't work if there is an image in the background. But for the use case you show in your image, it will work. – web-tiki May 08 '14 at 17:31
  • Here's a Fiddle: http://jsfiddle.net/qTT8X/ I'd really rather not set a background color for reasons you can see if you add `background-color: #DDDDDD;` to `#cataright` in the CSS. – gator May 08 '14 at 17:35
  • 1
    @riista I see the issue, this use case is diferent and needs an other aproach. I won't have time right now to find a solution until tomorrow but you could ask an other question for that specific use case, I am shure someon else can find a solution. – web-tiki May 08 '14 at 17:41
  • I appreciate all the help you've been, I got a little more digging around anyways. Cheers! – gator May 08 '14 at 17:43
  • 2
    @riista if the parent of the fieldset is just solid background (white), I'm sure you can use the solution provided by this answer, isn't this what you want http://jsfiddle.net/viphalongpro/qTT8X/1/ ? – King King May 08 '14 at 17:46
  • 1
    @KingKing, yes, actually, that's exactly what I needed. :) – gator May 08 '14 at 17:51
3

You can use :after pseudo selector to achieve this. SEE THE DEMO. This way, you don't have to use any additional html tags.

fieldset {
    position: relative;
}

fieldset:after {
    content: "Some Text";
    position: absolute;
    margin-top: -25px;
    right: 10px;
    background: #fff;
    padding: 0 5px;
}
Dhiraj
  • 1,871
  • 1
  • 12
  • 15
2

I had the same problem, but the answers here did not satisfy me. So I developed my own solution.
My solution is based on div-Tags. Just play with the width of the legend Tag and the width of the div Tag. Also you can set more Text.
Beneath you can find three different examples.

<fieldset style="border: 1px solid black; width: 500px; height: 100px; margin: 1em auto;">
 <legend style="width: 100%; padding: 0;">
  <div style="display: inline-block; line-height: 1.2;">
   <div style="float: left; padding: 0 5px;">Legend</div>
   <div style="float: left; height: 1px; background-color: black; width: 359px;  margin-top: 11px;"></div>
   <div style="float: left; padding: 0 5px;">Other Stuff</div>
  </div>
 </legend> 
</fieldset>
<fieldset style="border: 1px solid black; width: 500px; height: 100px; margin: 1em auto;">
 <legend style="width: 81%; padding: 0;">
  <div style="display: inline-block; line-height: 1.2;">
   <div style="float: left; height: 1px; background-color: black; width: 78px;  margin-top: 11px;"></div>
   <div style="float: left; padding: 0 5px;">Legend</div>
   <div style="float: left; height: 1px; background-color: black; width: 186px;  margin-top: 11px;"></div>
   <div style="float: left; padding: 0 5px;">Other Stuff</div>
  </div>
 </legend> 
</fieldset>
<fieldset style="border: 1px solid black; width: 500px; height: 100px; margin: 1em auto;">
 <legend style="width: 90%; padding: 0;">
  <div style="display: inline-block; line-height: 1.2;">
   <div style="float: left; height: 1px; background-color: black; width: 39px;  margin-top: 11px;"></div>
   <div style="float: left; padding: 0 5px;">Legend</div>
   <div style="float: left; height: 1px; background-color: black; width: 88px;  margin-top: 11px;"></div>
   <div style="float: left; padding: 0 5px;">More Stuff</div>     
   <div style="float: left; height: 1px; background-color: black; width: 102px;  margin-top: 11px;"></div>
   <div style="float: left; padding: 0 5px;">Other Stuff</div>
  </div>
 </legend> 
</fieldset>   

Note: display inline-block and line-height: 1.2 are necessary for cross browser compatibility.

Hans Dampf
  • 31
  • 3
1

Ok, I've managed to do it without the background color "hack", or using the fieldset tag, The only caveat is that trying to get rounded corners may be a bit tricky.

Basically our "panel" will be a box where we draw its left, bottom and right borders. Then our "panel-title" element will be absolutely positioned at the top of the panel.

Each panel span takes up exactly 50% of the panel width and uses display flex to do the magic. For the first span, we use the before element to draw the border 1em in width from the left-hand side, and then the after element we set the "flex-grow: 1" to tell it to take up the rest of the space.

Then we do exactly the same for the last span except having the width and flex-grow properties reversed. i.e. the last span's before element will instead be set to flex-grow: 1 and its after element will have a width of 1em.

Anyway, check the snippet below.

* { 
  box-sizing: border-box;
}
body {
  background:url(https://4.bp.blogspot.com/_AQ0vcRxFu0A/S9shDGGyMTI/AAAAAAAAAYk/kn3WTkY2LoQ/s1600/IMG_0714.JPG);
  background-size:cover;
  background-position:center center;
  background-attachment:fixed;
  margin: 0;
  font-family: 'Roboto Slab';
}

.panel {
  background: rgba(0,0,0,0.8);
  width: 75vw;
  height: -webkit-max-content;
  height: max-content;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  color: #fff;
  padding: 0.5em 1em;
  border-left: 1px solid #fff;
  border-bottom: 1px solid #fff;
  border-right: 1px solid #fff;
  
}
.panel-title {
  display: flex;
  position: absolute;
  left: 0;
  right: 0;
  top: -25px;
  height: 30px;
  line-height:30px;
  font-size: 30px;
  white-space: nowrap;
  text-shadow: 2px 2px 1px rgba(0,0,0,0.8);
}
.panel-title > span {
  display: flex;
  width: 50%;
}
.panel-title > span:before,
.panel-title > span:after {
  content: '';
  border-bottom:1px solid #fff;
  margin-bottom:5px;
  align-self:flex-end;
}
.panel-title > span:first-child:before {
  width: 1em;
  margin-right: 5px;
}
.panel-title > span:first-child:after {
  margin-left: 5px;
  flex-grow: 1;
}
.panel-title > span:last-child:before {
  flex-grow: 1;
  margin-right: 5px;
}
.panel-title > span:last-child:after {
  width: 1em;
  margin-left: 5px;
}
<link href='https://fonts.googleapis.com/css?family=Roboto+Slab:400,700' rel='stylesheet' type='text/css'>

<div class='panel'>
  <DIV class='panel-title'>
    <SPAN>Foo Bar</SPAN>
    <SPAN>Snee</SPAN>
  </DIV>
  <P>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent posuere tempus mauris at tincidunt.</P>
  <P>Phasellus facilisis leo tortor, nec molestie purus dignissim non. Integer massa turpis, porta sed erat sed.</P>
</div>
Jason
  • 31
  • 1
  • 7
0

Here is a responsive version using Bootstrap.

The custom CSS pushes the second legend up into place.

.legend {
  position: relative;
  top: -3.4em;
  margin-bottom: -3.4em;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">

<fieldset class="container border">
  <legend class="float-none w-auto p-2">Legend 1</legend>
  <div class="row legend">
    <div class="col-12">
      <span class="p-2 bg-white float-end">
          Legend 2
          <select></select>
        </span>
    </div>
  </div>
</fieldset>
Jens
  • 1,599
  • 14
  • 33