88

I'd like to have a div that looks like this:

border example

Is this possible to do with HTML + CSS? I will also be animating this div with jQuery. When the div is hidden I would like the title and the top line to show.

Alex Bliskovsky
  • 5,973
  • 7
  • 32
  • 41

10 Answers10

133

Yes, but it's not a div, it's a fieldset

fieldset {
    border: 1px solid #000;
}
<fieldset>
  <legend>AAA</legend>
</fieldset>
Flimm
  • 136,138
  • 45
  • 251
  • 267
Bazzz
  • 26,427
  • 12
  • 52
  • 69
  • 1
    You can make a workaround... Also, you should have commented that and not post it as an answer – JavierIEH Oct 11 '11 at 19:25
  • 8
    I don't see why it is a workaround, to me it is a solution. What functional difference does it make whether it's a div or a fieldset? – Bazzz Oct 11 '11 at 19:29
  • 6
    @Bazzz- it's wrong semantics. "The fieldset element represents a set of form controls optionally grouped under a common name." - HTML5 spec. Where are the controls? What we actually need is a `display:fieldset` CSS setting. Sadly there isn't one. – Alohci Oct 11 '11 at 19:33
  • Wow, sorry. I thought you were commenting on my answer. Nevermind – JavierIEH Oct 11 '11 at 19:33
  • 1
    @Alohci Agree! Though, I don't think the OP said there won't be any form controls in the fieldset. It could still be that he wants to put form controls inside :) – Bazzz Oct 11 '11 at 19:50
  • 3
    kudos for this, ten years later and I hadnt even heard of fieldsets until now. great answer – Cos Oct 27 '22 at 20:29
62

You can do something like this, where you set a negative margin on the h1 (or whatever header you are using)

div{
    height:100px;
    width:100px;
    border:2px solid black;
}

h1{
    width:30px;
    margin-top:-10px;
    margin-left:5px;
    background:white;
}

Note: you need to set a background as well as a width on the h1

Example: http://jsfiddle.net/ZgEMM/


EDIT

To make it work with hiding the div, you could use some jQuery like this

$('a').click(function(){
    var a = $('h1').detach();
    $('div').hide();
    $(a).prependTo('body');    
});

(You will need to modify...)

Example #2: http://jsfiddle.net/ZgEMM/4/

Jason Gennaro
  • 34,535
  • 8
  • 65
  • 86
  • 12
    I dont like this answer it has many constraints: the top margin is related to the font size of the h1, what if the font size changes later, you'd need to update all the margins. background: white prevents any background image from being visible throught the h1, it feels a little inflexible. I just have a feeling that using this approach is like opening up for more styling issues later. just my thought. – Bazzz Oct 11 '11 at 19:27
  • I like this. Is there a way to hide the side and bottom border when the div inside is hidden? http://jsfiddle.net/ZgEMM/3/ – Alex Bliskovsky Oct 11 '11 at 19:31
  • What I was asking was how to keep the top border and hide the other three, but I decided not to do that. This is what I ended up going with: http://jsfiddle.net/ZgEMM/10/ – Alex Bliskovsky Oct 11 '11 at 19:49
  • You will have problems if someone tries to print this page as browsers typically omit backgrounds by default. – Vivian River Jul 16 '15 at 20:20
  • Today I discussed this problem with a colleague. To prevent the issue from defining a fixed width (titles vary in length), we just used floating. So instead of `width: XXpx;` we use `float: left;`. – marcelion Mar 17 '17 at 15:48
20

I know a bit late to the party, however I feel the answers could do with some more investigation/input. I have managed to create the situation without using the fieldset tag - that is wrong anyway as if I'm not in a form then that isn't really what I should be doing.

/* Styles go here */

#info-block section {
    border: 2px solid black;
}

.file-marker > div {
    padding: 0 3px;
    height: 100px;
    margin-top: -0.8em;
    
}
.box-title {
    background: white none repeat scroll 0 0;
    display: inline-block;
    padding: 0 2px;
    margin-left: 8em;
}
<aside id="info-block">
  <section class="file-marker">
    <div>
      <div class="box-title">
        Audit Trail
      </div>
      <div class="box-contents">
        <div id="audit-trail">
        </div>
      </div>
    </div>
  </section>
</aside>

This can be viewed in this plunk:

Outline box with title

What this achieves is the following:

  • no use of fieldsets.

  • minimal use of CSS to create effect with just some paddings.

  • Use of "em" margin top to create font relative title.

  • use of display inline-block to achieve natural width around the text.

Anyway I hope that helps future stylers, you never know.

PeterS
  • 2,818
  • 23
  • 36
  • Despite being a little more complex than I'd like, I really like this answer because it isn't another CSS hack or bad practice. +1 – goncalotomas Jul 11 '16 at 09:30
  • Your Plunker link does not load. – HoldOffHunger Aug 21 '18 at 16:11
  • @HoldOffHunger seems to be working fine here, what browser did you try? – PeterS Aug 21 '18 at 21:18
  • Firefox, loads up and works perfect in Chrome. I was hoping an html/css demo wouldn't require much more, but Chrome is pretty standard sure. Glad to see an answer with an aside/section tag. – HoldOffHunger Aug 21 '18 at 21:34
  • @HoldOffHunger I may a slight improvement which may help Firefox, however I see that plunkr is going through some Alpha phases right now so it may not be 100%. – PeterS Aug 22 '18 at 09:25
  • The suggested code doesn't keep the CSS intact when the page gets resized. Whereas the same page resizing when tried using Fieldset (as suggested in the other answers) holds the CSS(box and the legend) intact. Hence, I don't think this is the suitable answer. – Lucifer Nov 02 '22 at 09:09
  • @Lucifer What do you mean "doesn't keep the CSS intact"? The code doesn't change the CSS on the fly. The original question is answered as is, please ask a new question if you have one. – PeterS Nov 02 '22 at 23:04
12

Text in Border with transparent text background

.box{
    background-image: url("https://i.stack.imgur.com/N39wV.jpg");
    width: 350px;
    padding: 10px;
}

/*begin first box*/
.first{
    width: 300px;
    height: 100px;
    margin: 10px;
    border-width: 0 2px 0 2px;
    border-color: #333;
    border-style: solid;
    position: relative;
}

.first span {
    position: absolute;
    display: flex;
    right: 0;
    left: 0;
    align-items: center;
}
.first .foo{
    top: -8px;
}
.first .bar{
    bottom: -8.5px;
}
.first span:before{
    margin-right: 15px;
}
.first span:after {
    margin-left: 15px;
}
.first span:before , .first span:after {
    content: ' ';
    height: 2px;
    background: #333;
    display: block;
    width: 50%;
}


/*begin second box*/
.second{
    width: 300px;
    height: 100px;
    margin: 10px;
    border-width: 2px 0 2px 0;
    border-color: #333;
    border-style: solid;
    position: relative;
}

.second span {
    position: absolute;
    top: 0;
    bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
}
.second .foo{
    left: -15px;
}
.second .bar{
    right: -15.5px;
}
.second span:before{
    margin-bottom: 15px;
}
.second span:after {
    margin-top: 15px;
}
.second span:before , .second span:after {
    content: ' ';
    width: 2px;
    background: #333;
    display: block;
    height: 50%;
}
<div class="box">
    <div class="first">
        <span class="foo">FOO</span>
        <span class="bar">BAR</span>
    </div>

   <br>

    <div class="second">
        <span class="foo">FOO</span>
        <span class="bar">BAR</span>
    </div>
</div>
Community
  • 1
  • 1
Mahdi Bashirpour
  • 17,147
  • 12
  • 117
  • 144
8

<fieldset>
  <legend> YOUR TITLE </legend>
  
  
  <p>
  Lorem ipsum dolor sit amet, est et illum reformidans, at lorem propriae mei. Qui legere commodo mediocritatem no. Diam consetetur.
  </p>
</fieldset>
Mahdi Bashirpour
  • 17,147
  • 12
  • 117
  • 144
4

You can use a fieldset tag.

<!DOCTYPE html>
<html>
<body>

<form>
 <fieldset>
  <legend>Personalia:</legend>
  Name: <input type="text"><br>
  Email: <input type="text"><br>
  Date of birth: <input type="text">
 </fieldset>
</form>

</body>
</html>

Check this link: HTML Tag

3

For a duplicate, here another option with transform, no fieldset ( and rounded border required in the duplicates) :

Question

enter image description here

Help. I am not great at UX. I am creating an app in React and using Material UI for the look. I really want to create something like this

Where the "Some Title" is a dynamic field from my database as well as the contents. The thing I cannot figure out is what is the best (non skanky) way to add the title into the outline? Thoughts?

Answer position or transform can help you too :

* {
  margin: 0;
  padding:0;
  box-sizing:border-box;
}

.fieldset {
  border: solid;
  color: #353fff;
  border-radius: 1em;
  margin: 2em 1em 1em;
  padding:0 1em 1em;
}

.legend {
  transform: translatey(-50%);
  width: max-content;
  background: white;
  padding: 0 0.15em;
}

.fieldset li {
  list-style-type: " - ";
}
<div class="fieldset">
  <h1 class="legend">Some Title</h1>
  <ul>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
    <li>Item</li>
  </ul>
</div>
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
  • The suggested code doesn't keep the CSS intact when the page gets resized. Whereas the same page resizing when tried using Fieldset (as suggested in the other answers) holds the CSS(box and the legend) intact. Hence, I don't think this is the suitable answer. – Lucifer Nov 02 '22 at 09:07
  • @Lucifer can you provide an example that breaks as you suggested :) ? ( this was an answer for https://stackoverflow.com/questions/63346035/title-inside-of-box-outline-css-frontend-dev-ux# which was tagged as a duplicate of that question here ... where markup could not be a form , + rounded borders ) – G-Cyrillus Nov 02 '22 at 21:36
0

If you are not in a position to add a field set, you can add a background to the element. In my situation, I had different colors in the input element and outside the input element, and also we have a hover color for the input element. So this is a fix I added linear-gradient background with outside color in the top half and transparent color in the bottom half. I added the transparent color to the bottom half inorder to see the hover color when hovered.

.class-name {
  background: linear-gradient(to bottom, #2a2b2d 50%, transparent 50%);
}
0

From a practical perspective, I think PeterS has the best answer. It's also presented in a very clear, didactical style.

Just to save others a few minutes converting it into more production-style code, I've done the following. Basically, it's what you would think you need: One div box inside another, with the outer div box providing the border, the inner providing the title contents with a negative margin shifting it up. A third div then contains the actual content.

This is the CSS:

   .outer-border-box {
border: 2px solid black; border-top:3px solid black;}


.label-source-box {
padding: 0 3px; height: 100px; margin-top: -0.8em; }

.box-title {
background: white none repeat scroll 0 0;
padding: 0 2px;
margin-left: 4em;
font-weight:700; font-size:18px; 
font-family: 'Avenir Next',Helvetica, sans-serif; }

This is the html:

    <div class="outer-border-box">
<div class="label-source-box">
<span class="box-title">Promotional </span>
<div class="box-contents">
<h2>this is the contents</h2>
</div> </div> </div>  
-1

It is possible by using the legend tag. Refer to http://www.w3schools.com/html5/tag_legend.asp

JavierIEH
  • 743
  • 8
  • 19
  • 3
    the `fieldset` and `legend` tags are _not_ HTML5 – Eonasdan Oct 11 '11 at 19:24
  • well, they do still exist in HTML 5, so technically... they are HTML 5 tags. :) – Bazzz Oct 11 '11 at 19:31
  • I just want to clarify this, I think it is correct to call it HTML5 as the interface has changed since HTML4.01. The HTML5 legend interface has obsoleted the accessKey and align attributes, whereas in HTML4.01 they are only deprecated. So there is a distinction. – Andrew Oct 11 '11 at 19:43
  • as I said those tags are _not_ HTML**5** those tags are **HTML**. the tags are not HTML5 only tags like `audio` is. – Eonasdan Oct 11 '11 at 20:35
  • Link is dead :( – Artemis Jun 20 '21 at 11:01