Add centered text to the middle of a horizontal rule

338,690

Solution 1

Flexbox is the solution:

.separator {
  display: flex;
  align-items: center;
  text-align: center;
}

.separator::before,
.separator::after {
  content: '';
  flex: 1;
  border-bottom: 1px solid #000;
}

.separator:not(:empty)::before {
  margin-right: .25em;
}

.separator:not(:empty)::after {
  margin-left: .25em;
}
<div class="separator">Next section</div>

Nowadays every browser supports it, and you can ensure compatibility with decade-old browsers by adding respective vendor prefixes if needed. It would degrade gracefully anyways.

Solution 2

How about:

<div style="width: 100%; height: 20px; border-bottom: 1px solid black; text-align: center">
  <span style="font-size: 40px; background-color: #F3F5F6; padding: 0 10px;">
    Section Title <!--Padding is optional-->
  </span>
</div>

Check out this JSFiddle.

You can use vw or % to make it responsive.

Solution 3

The way to solve this without knowing the width and the background color is the following:

Structure

<div class="strike">
   <span>Kringle</span>
</div>

CSS

.strike {
    display: block;
    text-align: center;
    overflow: hidden;
    white-space: nowrap; 
}

.strike > span {
    position: relative;
    display: inline-block;
}

.strike > span:before,
.strike > span:after {
    content: "";
    position: absolute;
    top: 50%;
    width: 9999px;
    height: 1px;
    background: red;
}

.strike > span:before {
    right: 100%;
    margin-right: 15px;
}

.strike > span:after {
    left: 100%;
    margin-left: 15px;
}

Example: http://jsfiddle.net/z8Hnz/

Double line

To create a double line, use one of the following options:

1) Fixed space between lines

.strike > span:before,
.strike > span:after {
    content: "";
    position: absolute;
    top: 50%;
    width: 9999px;
    border-top: 4px double red;

Example: http://jsfiddle.net/z8Hnz/103/

2) Custom space between lines

.strike > span:before,
.strike > span:after {
    content: "";
    position: absolute;
    top: 50%;
    width: 9999px;
    height: 5px; /* space between lines */
    margin-top: -2px; /* adjust vertical align */
    border-top: 1px solid red;
    border-bottom: 1px solid red;
}

Example: http://jsfiddle.net/z8Hnz/105/


SASS (SCSS) version

Based on this solution, I added SCSS "with color property" if it could help someone...

//mixins.scss
@mixin bg-strike($color) {

    display: block;
    text-align: center;
    overflow: hidden;
    white-space: nowrap; 

    > span {

        position: relative;
        display: inline-block;

        &:before,
        &:after {
            content: "";
            position: absolute;
            top: 50%;
            width: 9999px;
            height: 1px;
            background: $color;
        }

        &:before {
            right: 100%;
            margin-right: 15px;
        }

        &:after {
            left: 100%;
            margin-left: 15px;
        }
    }
}

example of use :

//content.scss
h2 {
    @include bg-strike($col1);
    color: $col1;
}

Solution 4

You can accomplish this with :before and :after without knowing the width of container or background color, and using them allows for greater styling of the line breaks. For example, this can be modified to make double-lines, dotted lines, etc.

JSFiddle

CSS, and HTML usage:

.hr-sect {
    display: flex;
    flex-basis: 100%;
    align-items: center;
    color: rgba(0, 0, 0, 0.35);
    margin: 8px 0px;
}
.hr-sect:before,
.hr-sect:after {
    content: "";
    flex-grow: 1;
    background: rgba(0, 0, 0, 0.35);
    height: 1px;
    font-size: 0px;
    line-height: 0px;
    margin: 0px 8px;
}
<div class="hr-sect">CATEGORY</div>

SCSS Version:

.hr-sect {
    display: flex;
    flex-basis: 100%;
    align-items: center;
    color: rgba(0, 0, 0, 0.35);
    margin: 8px 0;

    &:before, &:after {
        content: "";
        flex-grow: 1;
        background: rgba(0, 0, 0, 0.35);
        height: 1px;
        font-size: 0;
        line-height: 0;
        margin: 0 8px;
    }
}

Solution 5

Try this:

.divider {
	width:500px;
	text-align:center;
}

.divider hr {
	margin-left:auto;
	margin-right:auto;
	width:40%;

}

.left {
	float:left;
}

.right {
	float:right;
}
<div class="divider">
    <hr class="left"/>TEXT<hr class="right" />
</div>

Live preview on jsFiddle.

Share:
338,690

Related videos on Youtube

Brian M. Hunt
Author by

Brian M. Hunt

CTO and founder of MinuteBox.

Updated on July 16, 2021

Comments

  • Brian M. Hunt
    Brian M. Hunt almost 3 years

    I'm wondering what options one has in xhtml 1.0 strict to create a line on both sides of text like-so:

    Section one
    ----------------------- Next section -----------------------
    Section two
    

    I've thought of doing some fancy things like this:

    <div style="float:left; width: 44%;"><hr/></div>
    <div style="float:right; width: 44%;"><hr/></div>
    Next section
    

    Or alternatively, because the above has problems with alignment (both vertical and horizontal):

    <table><tr>
    <td style="width:47%"><hr/></td>
    <td style="vertical-align:middle; text-align: center">Next section</td>
    <td style="width:47%"><hr/></td>
    </tr></table>
    

    This also has alignment problems, which I solve with this mess:

    <table><tr>
    <td style="border-bottom: 1px solid gray; width: 47%">&nbsp;</td>
    <td style="vertical-align:middle;text-align:center" rowspan="2">Next section</td>
    <td style="border-bottom: 1px solid gray; width: 47%">&nbsp;</td>
    </tr><tr>
    <td>&nbsp;</td>
    <td>&nbsp;</td>
    </tr></table>
    

    In addition to the alignment problems, both options feel 'fudgy', and I'd be much obliged if you happened to have seen this before and know of an elegant solution.

    • willoller
      willoller over 11 years
      Here's another thread with a no-extra-tags challenge - and a solution! stackoverflow.com/questions/12648513/…
    • Admin
      Admin over 8 years
      stackoverflow.com/questions/5214127/… is still the best solution.
    • Brian M. Hunt
      Brian M. Hunt over 6 years
      A useful answer here would employ CSS Grid.
    • tao
      tao over 5 years
      Added an answer (SCSS) which transforms almost any element into a divider without set background and allows setting: color and stroke style (solid, dotted, dashed) of the divider, position of text (left, right, center), as well as the class which applies this (by default .divider).
    • MatTheCat
      MatTheCat over 4 years
      Given current flexbox support I think my answer could gain some visibility.
  • dclowd9901
    dclowd9901 about 14 years
    A more detailed explanation of what I was going for.
  • dclowd9901
    dclowd9901 about 14 years
    I'm pretty sure <legend> takes on the display traits of a block or inline-block element, as it can be padded and margined, which means text-align:center shouldn't work...
  • Nick Larsen
    Nick Larsen about 14 years
    I wouldn't call it a hack, but I would test that it works in all browsers you intend to support.
  • willoller
    willoller about 14 years
    yeah legends are great for semantics - i use them for wrapping radio groups but they are notoriously stubborn
  • Brian M. Hunt
    Brian M. Hunt about 14 years
    I like this, it looks great on your site, but I couldn't get it to work (I suspect interference from jQuery css). :( But it is really cool.
  • Trey Hunner
    Trey Hunner about 14 years
    I corrected my answer. Unfortunately due to the stubbornness of certain browsers in styling the legend element, align="center" is the only solution I could find that reliably centers a legend.
  • Dänu
    Dänu about 14 years
    fieldset doesn't want to be used like that, it's been hacked into place ;-)
  • Kirby
    Kirby over 12 years
    It works perfectly and uses <hr /> so what possibly could be wrong with this answer? I say nothing.
  • Mitar
    Mitar over 12 years
    Getting exact top value is a bit hard. It is not exactly -0.5em;
  • imns
    imns about 12 years
    I think your h1 is pushing the span down.
  • Nix
    Nix almost 12 years
    Welcome to StackOverflow, Youri. Instead of a span, you could consider using a div. It serves the same purpose, except it is naturally a block element. :)
  • Peter
    Peter over 11 years
    This is a "hack" that employs the different rendering behaviour for DOCTYPE XTHML 1.0 Transitional. If you use DOCTYPE html (for HTML5), it will NOT work.
  • Jonathan
    Jonathan over 11 years
    @Nix Block element inside inline element? No thanks, span is a good choice
  • Nix
    Nix over 11 years
    @MrAzulay h1 is an inline element. span is nice for wrapping stuff, but the reason I prefer a div in this case, is because Youri use CSS to set the span to display:block;. I don't see the point of making an inline element into a block element, when there are suitable block elements (div) readily available.
  • Jonathan
    Jonathan over 11 years
    @Nix Isn't that a pretty common thing to do? While putting blocks inside inline is bad practice imo. This is a good post about it skypoetsworld.blogspot.se/2008/10/…
  • Nix
    Nix over 11 years
    Ooops, I mistyped in my latest comment. I agree that you shouldn't place a block inside an inline element, but h1 is actually a BLOCK element. Sorry for the confusion. Still, I don't see the point of making a span into a block element, but fair enough.
  • Kelvin
    Kelvin over 11 years
    +1 No need to mess with background color or use tags in unintended ways. One downside is that .divider hr width depends on how long the text is. Suggestion: .divider and .divider hr widths should be specified in em units. To get hr width, use (.divider width minus # of chars) / 2 .
  • Dracorat
    Dracorat about 11 years
    Doesn't solve the OP's problem. That creates two lines with text between them. He wants a line that's broken part way through and has text at the broken section, then the line continues.
  • Robert Kajic
    Robert Kajic about 11 years
    It actually does what the OP is asking for. You can see it at jsfiddle.net/88vgS
  • Robert Kajic
    Robert Kajic about 11 years
    Also, what is a line broken part way through, with text at the broken section, if not two lines with text in between them?
  • Dracorat
    Dracorat about 11 years
    You should throw appropriate TR tags in there. I think that's what got me confused for a moment. I originally thought for some reason it was on three lines, not three columns. Correct markup probably wouldn't have caused me to see it that way. Regardless, it's definitely a workable solution.
  • Nicholas Petersen
    Nicholas Petersen over 10 years
    But this uses tables, that is a NOT ALLOWED! Oh, just kidding. GRIDS have their place, almost all other GUI XML frameworks recognize that and use them everywhere (e.g. WPF / XAML). Thanks for the solution mate! This deserves more than 3 up votes. I suspect people's aversion to the hated tables will be an obstacle though.
  • JimXC
    JimXC over 10 years
    perfect. "Responsive" too
  • iCeStar
    iCeStar about 10 years
    See my answer for a solution that doesn't require you to specify the background color or the width.
  • tehlivi
    tehlivi about 10 years
    This version works better if you are using an image for the line -- or at least it is easier to edit and remain responsive
  • tehlivi
    tehlivi about 10 years
    Fieldsets should only be used with forms.
  • wloescher
    wloescher almost 10 years
    Very nice work! Can you use your wizardry to create a double line? (Otherwise, I'll just resort to using a tiny repeating background image.)
  • plong0
    plong0 almost 9 years
    Great snippet! Thanks :)
  • Dinesh Dabhi
    Dinesh Dabhi over 8 years
    This is the best answer because it will work without the setting the background , and when you have to set the transparent background
  • Luiz Eduardo
    Luiz Eduardo over 8 years
    The first example is simply awesome! Congrats! It should be the correct answer!
  • Farside
    Farside about 8 years
    Elegant solution, though it has one caveat: if there will be no text, you'll still have a gap between lines.
  • Robert
    Robert almost 8 years
    This is the cleanest solution in this thread to be honest, the issue with no text can be overlooked since you would want the divider with text always.
  • alaster
    alaster over 7 years
    Very nice example. Also you can align text to left, center and right and it works as expected - unwanted line will disappear. But you need to remove text-align: center; for this to work
  • akivajgordon
    akivajgordon over 6 years
    Best answer considering flexbox support these days
  • Diosney
    Diosney almost 6 years
    To hide overflowing lines to both sides, just set overflow: hidden to the parent and voila, constrained striked lines.
  • db0
    db0 almost 6 years
    An updated version that will show a single line without interruption when there is no title: jsfiddle.net/z8Hnz/1901
  • tao
    tao over 5 years
    See my answer for responsive, transparent bg, variable style and height of divider, variable position of text. Can also be applied more than once to different selectors, for having more than one style of divider in the same project, using SCSS. Works with any font-size.
  • Cameron Hudson
    Cameron Hudson almost 5 years
    The vertical-center class no longer exists in bootstrap (4.3.1). Could you please update your answer to say align-items-center?
  • cadenzah
    cadenzah almost 5 years
    Hi, I really appreciate your code snippet. If I put a text with divider other than english (in my case, korean), texts break line in every two letters. Could you figure out why?
  • Vignesh
    Vignesh over 4 years
    Great and reusable solution, like a utility class.
  • TomSawyer
    TomSawyer over 4 years
    40% is wrong here. If the text is longer, it would mis-aligned
  • Smaillns
    Smaillns about 4 years
    this is a nice solution
  • Erdem Ergin
    Erdem Ergin over 3 years
    I believe placing a span and giving margins to it instead of pseudo classes is more flexible solution for providing margins to text. In this way, it can be used as a single separator component with or without a text. <div class="separator"><span>Next section</span></div> .separator span { margin-left: .25em; margin-right: .25em; }
  • MatTheCat
    MatTheCat over 3 years
    @ErdemErgin I edited my answer to address your use-case.
  • Christos Lytras
    Christos Lytras over 2 years
    Change background: rgba(0, 0, 0, 0.35); with border-top: 1px dashed rgba(0, 0, 0, 0.35); to control the line style.
  • sohammondal
    sohammondal about 2 years
    perfect solution!