CSS technique for a horizontal line with words in the middle
Solution 1
This is roughly how I'd do it: the line is created by setting a border-bottom
on the containing h2
then giving the h2
a smaller line-height
. The text is then put in a nested span
with a non-transparent background.
h2 {
width: 100%;
text-align: center;
border-bottom: 1px solid #000;
line-height: 0.1em;
margin: 10px 0 20px;
}
h2 span {
background:#fff;
padding:0 10px;
}
<h2><span>THIS IS A TEST</span></h2>
<p>this is some content other</p>
I tested in Chrome only, but there's no reason it shouldn't work in other browsers.
JSFiddle: http://jsfiddle.net/7jGHS/
Solution 2
After trying different solutions, I have come with one valid for different text widths, any possible background and without adding extra markup.
h1 {
overflow: hidden;
text-align: center;
}
h1:before,
h1:after {
background-color: #000;
content: "";
display: inline-block;
height: 1px;
position: relative;
vertical-align: middle;
width: 50%;
}
h1:before {
right: 0.5em;
margin-left: -50%;
}
h1:after {
left: 0.5em;
margin-right: -50%;
}
<h1>Heading</h1>
<h1>This is a longer heading</h1>
I tested it in IE8, IE9, Firefox and Chrome. You can check it here http://jsfiddle.net/Puigcerber/vLwDf/1/
Solution 3
Here is Flex based solution.
h1 {
display: flex;
flex-direction: row;
}
h1:before, h1:after{
content: "";
flex: 1 1;
border-bottom: 1px solid;
margin: auto;
}
h1:before {
margin-right: 10px
}
h1:after {
margin-left: 10px
}
<h1>Today</h1>
JSFiddle: https://jsfiddle.net/j0y7uaqL/
Solution 4
Shortest and best method:
span:after,
span:before{
content:"\00a0\00a0\00a0\00a0\00a0";
text-decoration:line-through;
}
<span> your text </span>
Solution 5
Ok, this one is more complicated but it works in everything but IE<8
<div><span>text TEXT</span></div>
div {
text-align: center;
position: relative;
}
span {
display: inline-block;
}
span:before,
span:after {
border-top: 1px solid black;
display: block;
height: 1px;
content: " ";
width: 40%;
position: absolute;
left: 0;
top: 1.2em;
}
span:after {
right: 0;
left: auto;
}
The :before and :after elements are positioned absolutely so we can pull one to the left and one to the right. Also, the width (40% in this case) is very dependent of the width of the text inside.. have to think about a solution for that. At least the top: 1.2em
makes sure the lines stay more or less in the center of the text even if you have different font size.
It does seem to work well though: http://jsfiddle.net/tUGrf/3/
Jason
I'm a web developer who works in PHP/MySQL/SQLite and Server side Javascript: http://bondijs.org
Updated on January 14, 2022Comments
-
Jason over 2 years
I'm trying to make a horizontal rule with some text in the middle. For example:
----------------------------------- my title here -----------------------------
Is there a way to do that in CSS? Without all the "-" dashes obviously.
-
Marnix over 13 yearsNice, only problem is that you have to set the background to white and can't set it to transparent.
-
Stephan Muller over 13 yearsin that case you'll have to work with two lines, one on each side. That's going to be difficult to achieve in a clean way..
-
thirtydot over 13 yearsThese are clever, but I sure hope the OP doesn't want this for inside a
form
tag. If he does, as I'm sure you know, he could simply usefieldset
andlegend
. -
Stephan Muller over 13 yearsHeh, you're right about that. Might as well go for that anyway if this doesn't work.. not semantically correct but it's better than having to resort to javascript for something like this imo.
-
DrLazer almost 12 yearsThis is my favourite solution. It works on OSX too and some of the others dont. If you use this solution remember to set the background of the span to the same color as the background of your page, it will be especially obvious what i mean if your background isn't white. ;)
-
Luke about 11 yearsThis really is a good solution; particularly as it works with any background and does not require a set width on the heading element.
-
BeetleTheNeato over 10 yearsThis is great. I adapted your code a bit to left-align the text and make the
:after
element the width of the block. I'm curious: what exactly is the role ofmargin-right: -50%
? When I was fumbling around with code, missing that property would make the decoration break to another line. And even when:after
is assigned 100% width, I still need the negative margin-right of 50% to make it fit. Why? -
Puigcerber over 10 yearsAs I understand it, adding negative margins in both sides pulls the element in both direction so that's why it gets centered.
-
Xavier John over 10 yearsThe best solution I found that works well when the screen is resided and without setting the background color of the text is jsfiddle.net/vLwDf/268
-
Chao about 8 yearsThis is not flexible, since you fix the background color of the text as white.
-
JoeMoe1984 over 7 yearsOne of the things I love about this solution is that it works for situations where you don't know what color the background is. Easily the best solution so far for this problem.
-
Mikhail Vasin almost 7 yearsIn my case line appeared to be a bit to thick, so I hacked it by assigning a different font family:
font-family: monospace;
worked fine. -
Jesse Buitenhuis about 6 yearsI use another element:
<h1><span>Today</span></h1>
with a margin/padding on the span. -
Christian Michael over 5 yearsI created a scss example with placeholder codepen.io/cmichael110/pen/KJLxBq. @Matt__C Your solution with the left alignment is also a good thing - maybe someone here can extend it with a fullwidth line.
-
maxi-code over 5 yearsIf you have small width and large text then the cross line is not working as expected.. wrap all the html in a div with width: 150px. How can you solve that? I'm looking a responsive solution as this part of my app will be shown in mobile devices
-
Nikita Fedyashev almost 5 yearsMy favorite approach so far but unfortunately it doesn't work in email clients for some reason(Gmail mobile & web)
-
Emerson over 4 yearsHow can I restrict this to a certain class, as I can't have this applied to all of the heading, just to some of them. I trie to use "h2.titulo:before{..." but it didn't work.
-
Puigcerber over 4 yearsYeah, that should work @emerson, or even just the class
.titulo:before
. -
S.Goswami almost 4 yearsWhile this is easy and clever, this just creates a strike-through on the word and hides it with a padding and a background colour to the span. So if you have a background colour that is defined by the user, you have to change the background colour of the span as well. In my case, I enable user to switch between dark and lite mode. I have to update the span colour every-time the user switches the colour. That's a painful situation. So it's good idea to make use of the pseudo elements here, as written by @Puigcerber. So I made line is grey, will work in both lite and dark mode.
-
fregante over 3 yearsThe padding is achieved via the existing margin left/right you see in the demo.
-
vikramvi about 3 yearsSimple and sweet, works perfectly with tailwind css as well with this solution, thanks for sharing
-
Jed Lynch over 2 yearsI think this is the more robust solution. This will work if you need to insert an icon between the lines.
-
Jed Lynch over 2 yearsThis will not work with media queries.
-
Sebi2020 over 2 years
::before
not:before
-
mercury over 2 yearsthis is the simplest solution
-
mercury over 2 yearsI create a small background .png image and put it as a background .
-
Nimble Stalker over 2 yearsIt's good solution but if you use language like Russian you need to add
padding
because this language have a letters like Й and top of this letter is hidden -
Rendy The Code over 2 yearsIt's only worked for specific background color. It's not working when using transparent background
-
John Magnolia about 2 yearsWith latest version you can do it without adding extra HTML even more awesome.
before:mr-2 before:block before:flex-1 before:border-b-2 before:border-gray-200 after:ml-2 after:block after:flex-1 after:border-b-2 after:border-gray-200 lg:before:mr-4 lf:after:ml-4
-
Mateusz Osuch about 2 yearsIf it's flex-based solution, I would add
align-items: center;
to theh1
definition so nomargin: auto
is needed