Técnica CSS para una línea horizontal con palabras en el medio


286

Estoy tratando de hacer una regla horizontal con algo de texto en el medio. Por ejemplo:

----------------------------------- mi título aquí ------------ -----------------

¿Hay alguna manera de hacer eso en CSS? Sin todos los guiones "-" obviamente.


¿Es esto por dentro de una formetiqueta?
thirtydot

en ese caso, como señaló thirtydot en respuesta a mi respuesta, es posible que desee buscar los elementos fieldsetylegend
Stephan Muller


Para una solución sobre un fondo transparente , vea Línea antes y después del texto centrado sobre fondo transparente
web-tiki

Respuestas:


404

Esto es más o menos como lo haría: la línea se crea estableciendo un border-bottomen el contenedor y h2luego dando h2un más pequeño line-height. El texto se coloca anidado spancon un fondo no transparente.

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>

Probé solo en Chrome, pero no hay razón para que no funcione en otros navegadores.

JSFiddle: http://jsfiddle.net/7jGHS/


3
Esta es mi solución favorita. Funciona también en OSX y algunos de los otros no. Si utiliza esta solución, recuerde establecer el fondo del lapso en el mismo color que el fondo de su página, será especialmente obvio lo que quiero decir si su fondo no es blanco. ;)
DrLazer

1
¿Alguna forma de hacer esto alrededor de una cuarta parte del camino?
Troy Cosentino

1
Obtenga el texto sangrado desde la izquierda usando "text-align: left; text-indent: 40px;" en el estilo h2.
Matt__C

14
Esto no es flexible, ya que fija el color de fondo del texto como blanco.
Chao

2
@NateBarbettini A menos que la línea en la que intentas hacer esto y el texto necesite tener fondos transparentes para las otras cosas detrás de ella.
Coburn

265

Después de probar diferentes soluciones, he llegado con una válida para diferentes anchos de texto, cualquier fondo posible y sin agregar marcas adicionales.

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>

Lo probé en IE8, IE9, Firefox y Chrome. Puede consultarlo aquí http://jsfiddle.net/Puigcerber/vLwDf/1/


2
Este me gusta más también. Para obtener un estilo donde el texto esté sangrado desde la izquierda en lugar de centrado, use este cambio: h1 { desbordamiento: oculto; `text-align: left; `text-indent: 40px; `}
Matt__C

9
Esta es realmente una buena solución; particularmente porque funciona con cualquier fondo y no requiere un ancho establecido en el elemento de encabezado.
Lucas

2
Esto es genial. Adapte un poco su código para alinear a la izquierda el texto y hacer que el :afterelemento tenga el ancho del bloque. Tengo curiosidad: ¿cuál es exactamente el papel de margin-right: -50%? Cuando estaba buscando un código, perder esa propiedad haría que la decoración saltara a otra línea. E incluso cuando :afterse le asigna un ancho del 100%, todavía necesito el margen negativo derecho del 50% para que encaje. ¿Por qué?
BeetleTheNeato

Según tengo entendido, agregar márgenes negativos en ambos lados tira del elemento en ambas direcciones, por eso se centra.
Puigcerber

2
Una de las cosas que me encantan de esta solución es que funciona para situaciones en las que no sabes de qué color es el fondo. Fácilmente la mejor solución hasta ahora para este problema.
JoeMoe1984

54

Ok, este es más complicado pero funciona en todo menos 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; 
}

Los elementos: before y: after están posicionados absolutamente para que podamos tirar uno hacia la izquierda y otro hacia la derecha. Además, el ancho (40% en este caso) es muy dependiente del ancho del texto dentro ... tengo que pensar en una solución para eso. Al menos, top: 1.2emse asegura de que las líneas permanezcan más o menos en el centro del texto, incluso si tiene un tamaño de fuente diferente.

Sin embargo, parece funcionar bien: http://jsfiddle.net/tUGrf/3/


3
Estos son inteligentes, pero espero que el OP no quiera esto dentro de una formetiqueta. Si lo hace, como estoy seguro de que sabe, simplemente podría usar fieldsety legend.
thirtydot

1
Je, tienes razón en eso. De todos modos, podría hacerlo si esto no funciona ... no es semánticamente correcto, pero es mejor que tener que recurrir a JavaScript para algo como esto.
Stephan Muller

8
La mejor solución que encontré que funciona bien cuando la pantalla reside y sin establecer el color de fondo del texto es jsfiddle.net/vLwDf/268
Xavier John

Sí @ xavier-john, esa es mi respuesta ;)
Puigcerber

43

El método más corto y mejor:

span:after,
span:before{
    content:"\00a0\00a0\00a0\00a0\00a0";
    text-decoration:line-through;
}
<span> your text </span>


44
Debe agregar una descripción de lo que hace su código, a menos que desee que se elimine.
inf3rno

En mi caso, la línea parecía ser un poco gruesa, así que la pirateé asignando una familia de fuentes diferente: font-family: monospace;funcionó bien.
Mikhail Vasin

38

Aquí está la solución basada en Flex.

Un rumbo con una línea horizontal central a los lados.

h1 {
  display: flex;
  flex-direction: row;
}
h1:before, h1:after{
  content: "";
  flex: 1 1;
  border-bottom: 1px solid #000;
  margin: auto;
}
h1:before {
  margin-right: 10px
}
h1:after {
  margin-left: 10px
}
<h1>Today</h1>

JSFiddle: https://jsfiddle.net/yoshiokatsuneo/3h1fmj29/


¿Cómo conseguir el relleno?
Sylar

rápido y sucio, puede agregar un & nbsp;
chrismarx

1
Yo uso otro elemento: <h1><span>Today</span></h1>con un margen / relleno en el lapso.
Jesse Buitenhuis

19

para el navegador posterior (hoy en día), display:flexyd pseudo-elements hace que sea fácil dibujar. border-style, box-shadowe incluso backgroundayuda también para el maquillaje. demostración a continuación

h1 {margin-top:50px;
  display:flex;
  background:linear-gradient(to left,gray,lightgray,white,yellow,turquoise);;
}
h1:before, h1:after {
  color:white;
  content:'';
  flex:1;
  border-bottom:groove 2px;
  margin:auto 0.25em;
  box-shadow: 0 -1px ;/* ou 0 1px si border-style:ridge */
}
<h1>side lines via flex</h1>


¡Gracias por esto, muy hábil!
Jimmy Obonyo Abor

Perfecta, única solución que funcionó para mí cuando era una imagen de fondo
cjohansson

12

.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">Text</div>


9
<div><span>text TEXT</span></div>

div { 
  height: 1px; 
  border-top: 1px solid black; 
  text-align: center; 
  position: relative; 
}
span { 
  position: relative; 
  top: -.7em; 
  background: white; 
  display: inline-block; 
}

Déle un espacio al espacio para que haya más espacio entre el texto y la línea.

Ejemplo: http://jsfiddle.net/tUGrf/


1
Agradable, el único problema es que debe establecer el fondo en blanco y no puede establecerlo en transparente.
Marnix

en ese caso tendrás que trabajar con dos líneas, una a cada lado. Eso va a ser difícil de lograr de una manera limpia ..
Stephan Muller

Mi enfoque favorito hasta ahora, pero desafortunadamente no funciona en clientes de correo electrónico por alguna razón (Gmail mobile & web)
reedwolf

9

He estado buscando algunas soluciones para esta decoración simple y he encontrado algunas, algunas extrañas, algunas incluso con JS para calcular la altura de la fuente y bla, bla, bla, luego he leído el uno en esta publicación y lea un comentario de thirtydot hablando fieldsetylegend y pensé que era él.

Estoy anulando esos estilos de 2 elementos, supongo que podría copiar los estándares del W3C e incluirlos en su .middle-line-textclase (o como quiera llamarlo), pero esto es lo que hice:

<fieldset class="featured-header">
    <legend>Your text goes here</legend>
</fieldset>

<style>
.featured-header{
    border-bottom: none;
    border-left: none;
    border-right: none;
    text-align: center;
 }

.featured-header legend{
    -webkit-padding-start: 8px; /* It sets the whitespace between the line and the text */
    -webkit-padding-end: 8px; 
    background: transparent; /** It's cool because you don't need to fill your bg-color as you would need to in some of the other examples that you can find (: */
    font-weight: normal; /* I preffer the text to be regular instead of bold  */
    color: YOU_CHOOSE;
}   

</style>

Aquí está el violín: http://jsfiddle.net/legnaleama/3t7wjpa2/

He jugado con los estilos de borde y también funciona en Android;) (Probado en kitkat 4.XX)

EDITAR:

Siguiendo la idea de Bekerov Artur, que también es una buena opción, he cambiado la imagen .png base64 para crear el trazo con un .SVG para que pueda renderizar en cualquier resolución y también cambiar el color del elemento sin ningún otro software involucrado :)

/* SVG solution based on Bekerov Artur */
/* Flexible solution, scalable, adaptable and also color customizable*/
.stroke {
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' width='1px' height='1px' viewBox='0 0 1 1' enable-background='new 0 0 1 1' fill='%23ff6600' xml:space='preserve'><rect width='1' height='1'/></svg>");
background-repeat: repeat-x;
background-position: left;
text-align: center;
}
.stroke h3 {
background-color: #ffffff;
margin: 0 auto;
padding:0 10px;
display: inline-block;
font-size: 66px;
}

5

Solución para IE8 y más reciente ...

Cuestiones dignas de mención:

Utilizando background-color para enmascarar un borde podría no ser la mejor solución. Si tiene un color de fondo (o imagen) complejo (o desconocido), la máscara finalmente fallará. Además, si cambia el tamaño del texto, notará que el color de fondo blanco (o lo que establezca) comenzará a cubrir el texto en la línea superior (o inferior).

Tampoco quiere "adivinar" qué tan anchas son las secciones, ya que hace que los estilos sean muy inflexibles y casi imposibles de implementar en un sitio receptivo donde el ancho del contenido está cambiando.

Solución:

( Ver JSFiddle )

En lugar de "enmascarar" un borde con un background-color, use su displaypropiedad.

HTML

<div class="group">
    <div class="item line"></div>
    <div class="item text">This is a test</div>
    <div class="item line"></div>
</div>

CSS

.group { display: table; width: 100%; }
.item { display: table-cell; }
.text { white-space: nowrap; width: 1%; padding: 0 10px; }
.line { border-bottom: 1px solid #000; position: relative; top: -.5em; }

Cambie el tamaño de su texto colocando su font-sizepropiedad en el.group elemento.

Limitaciones:

  • No hay texto de varias líneas. Solo líneas individuales.
  • El marcado HTML no es tan elegante
  • topLa propiedad del .lineelemento debe ser la mitad de line-height. Entonces, si tienes un line-heightde 1.5em, entonces el topdebería ser -.75em. Esto es una limitación porque no está automatizado, y si está aplicando estos estilos en elementos con diferentes alturas de línea, es posible que deba volver a aplicar su line-heightestilo.

Para mí, estas limitaciones superan los "problemas" que noté al comienzo de mi respuesta para la mayoría de las implementaciones.


Funciona en cromo. Parece semántico y bastante simple. Funciona con bootstrap.
Jeff Ancel

Tuve que agregar border-collapse: separe a .group, porque lo estoy usando en el poder que tiene una configuración diferente. Funciona genial.
Brian MacKay

5

Esto le proporciona una longitud fija para las líneas, pero funciona muy bien. Las longitudes de las líneas se controlan agregando o tomando '\ 00a0' (espacio unicode).

ingrese la descripción de la imagen aquí

h1:before, h1:after {
  content:'\00a0\00a0\00a0\00a0';
  text-decoration: line-through;
  margin: auto 0.5em;
}
<h1>side lines</h1>


2

Si alguien se pregunta cómo configurar el encabezado de modo que aparezca con una distancia fija hacia el lado izquierdo (y no centrado como se presentó anteriormente), lo descubrí modificando el código de @ Puigcerber.

h1 {
  white-space: nowrap;
  overflow: hidden;
}

h1:before, 
h1:after {
  background-color: #000;
  content: "";
  display: inline-block;
  height: 1px;
  position: relative;
  vertical-align: middle;
}

h1:before {
  right: 0.3em;
  width: 50px;
}

h1:after {
  left: 0.3em;
  width: 100%;
}

Aquí el JSFiddle .


2
h6 {
    font: 14px sans-serif;
    margin-top: 20px;
    text-align: center;
    text-transform: uppercase;
    font-weight: 900;
}

    h6.background {
        position: relative;
        z-index: 1;
        margin-top: 0%;
        width:85%;
        margin-left:6%;
    }

        h6.background span {
            background: #fff;
            padding: 0 15px;
        }

        h6.background:before {
            border-top: 2px solid #dfdfdf;
            content: "";
            margin: 0 auto; /* this centers the line to the full width specified */
            position: absolute; /* positioning must be absolute here, and relative positioning must be applied to the parent */
            top: 50%;
            left: 0;
            right: 0;
            bottom: 0;
            width: 95%;
            z-index: -1;
        }

Esto te ayudara


entre linea

<h6 class = "background"> ​​<span> <br> NUESTROS SERVICIOS </span> </h6> este es el código html
Dominic Amal Joe F

Joe, puedes editar tu propia respuesta para agregar el código HTML, mucho mejor que ponerlo en los comentarios. También debe agregar alguna explicación a la respuesta.
Mogsdad

Lo siento, Mogsdad, olvidé poner el código html, por eso lo puse aquí.
Dominic Amal Joe F

2

Utilizo un diseño de tabla para llenar los lados dinámicamente y divisiones de posición absoluta en altura 0 para el posicionamiento vertical dinámico:

ingrese la descripción de la imagen aquí

  • sin dimensiones codificadas
  • Sin imágenes
  • sin pseudo-elementos
  • respeta el fondo
  • apariencia de la barra de control

https://jsfiddle.net/eq5gz5xL/18/

Descubrí que un poco por debajo del centro verdadero se ve mejor con texto; Esto se puede ajustar donde 55%está (la altura más alta hace que la barra sea más baja). La apariencia de la línea se puede cambiar donde elborder-bottom está.

HTML:

<div class="title">
  <div class="title-row">
    <div class="bar-container">
      <div class="bar"></div>
    </div>
    <div class="text">
      Title
    </div>
    <div class="bar-container">
      <div class="bar"></div>
    </div>
  </div>
</div>

CSS:

.title{
  display: table;
  width: 100%
  background: linear-gradient(to right, white, lightgray);
}
.title-row{
  display: table-row;
}
.bar-container {
  display: table-cell;
  position: relative;
  width: 50%;
}
.bar {
  position: absolute;
  width: 100%;
  top: 55%;
  border-bottom: 1px solid black;
}
.text {
  display: table-cell;
  padding-left: 5px;
  padding-right: 5px;
  font-size: 36px;
}

2

No para vencer a un caballo muerto, pero estaba buscando una solución, terminé aquí, y no estaba satisfecho con las opciones, sobre todo por alguna razón no pude obtener las soluciones proporcionadas aquí para que funcionaran bien para mí. (Probablemente debido a errores de mi parte ...) Pero he estado jugando con flexbox y aquí hay algo que pude trabajar por mí mismo.

Algunas de las configuraciones están cableadas, pero solo con fines de demostración. Creo que esta solución debería funcionar en casi cualquier navegador moderno. Simplemente elimine / ajuste la configuración fija para la clase .flex-parent, ajuste los colores / texto / material y (espero) que estará tan feliz como yo con este enfoque.

HTML:

.flex-parent {
  display: flex;
  width: 300px;
  height: 20px;
  align-items: center;
}

.flex-child-edge {
  flex-grow: 2;
  height: 1px;
  background-color: #000;
  border: 1px #000 solid;
}
.flex-child-text {
  flex-basis: auto;
  flex-grow: 0;
  margin: 0px 5px 0px 5px;
  text-align: center;
}
<div class="flex-parent">
  <div class="flex-child-edge"></div>
  <div class="flex-child-text">I found this simpler!</div>
  <div class="flex-child-edge"></div>
</div>

También guardé mi solución aquí: https://jsfiddle.net/Wellspring/wupj1y1a/1/


1

En caso de que alguien quiera, en mi humilde opinión, la mejor solución usando CSS es por un flexbox.

Aquí hay un ejemplo:

.kw-dvp-HorizonalButton {
    color: #0078d7;
    display:flex;
    flex-wrap:nowrap;
    align-items:center;
}
.kw-dvp-HorizonalButton:before, .kw-dvp-HorizonalButton:after {
    background-color: #0078d7;
    content: "";
    display: inline-block;
    float:left;
    height:1px;
}
.kw-dvp-HorizonalButton:before {
    order:1;
    flex-grow:1;
    margin-right:8px;
}
.kw-dvp-HorizonalButton:after {
    order: 3;
    flex-grow: 1;
    margin-left: 8px;
}
.kw-dvp-HorizonalButton * {
    order: 2;
}
    <div class="kw-dvp-HorizonalButton">
        <span>hello</span>
    </div>

Esto siempre debe dar como resultado un contenido alineado perfectamente centrado con una línea a la izquierda y a la derecha, con un margen fácil de controlar entre la línea y su contenido.

Crea un elemento de línea antes y después de su control superior y los configura en el orden 1,3 en su contenedor flexible mientras configura su contenido como orden 2 (ir en el medio). dar el antes / después de un crecimiento de 1 hará que consuman el espacio más vacante por igual mientras mantienen su contenido centrado.

¡Espero que esto ayude!


0

No estoy muy seguro, pero podría intentar usar una regla horizontal y empujar el texto por encima de su margen superior. Necesitará un ancho fijo en su etiqueta de párrafo y un fondo también. Es un poco hacky y no sé si funcionará en todos los navegadores, y debe establecer el margen negativo en función del tamaño de la fuente. Sin embargo, funciona en Chrome.

<style>   
 p{ margin-top:-20px; background:#fff; width:20px;}
</style>

<hr><p>def</p>

0

He intentado la mayoría de las formas sugeridas, pero termina con algunos problemas como ancho completo o No adecuado para contenido dinámico. Finalmente modifiqué un código y funciona perfectamente. Este código de ejemplo dibujará esas líneas antes y después, y es flexible en el cambio de contenido. Centro alineado también.

HTML

        <div style="text-align:center"> 
            <h1>
                <span >S</span>
            </h1> 
        </div> 

        <div style="text-align:center"> 
            <h1>
                <span >Long text</span>
            </h1> 
        </div> 

CSS

      h1 {
            display: inline-block;
            position: relative;
            text-align: center;
        }

        h1 span {
            background: #fff;
            padding: 0 10px;
            position: relative;
            z-index: 1;
        }

        h1:before {
            background: #ddd;
            content: "";
            height: 1px;
            position: absolute;
            top: 50%;
            width: calc(100% + 50px);//Support in modern browsers
            left: -25px;
        }

        h1:before {
            left: ;
        }

Resultado: https://jsfiddle.net/fasilkk/vowqfnb9/


0

Para mí, esta solución funciona perfectamente bien ...

HTML

<h2 class="strikethough"><span>Testing Text</span></h2>

CSS

.strikethough {
 width:100%; 
 text-align:left; 
 border-bottom: 1px solid #bcbcbc; 
 overflow: inherit;
 margin:0px 0 30px;
 font-size: 16px;
 color:#757575;
 }
.strikethough span {
 background:#fff; 
 padding:0 20px 0px 0px;
 position: relative;
 top: 10px;
}

0

Las personas que usan Bootstrap 4 pueden lograrlo con este método. Las clases mencionadas en el código HTML son de Bootstrap 4.

h1 {
    position: relative;
    flex-grow: 1;
    margin: 0;
}

h1:before {
   content: "";
   display: block;
   border-top: solid 2px blue;
   width: 100%;
   height: 1px;
   position: absolute;
   top: 50%;
   z-index: 1;
 }
 h1 span {
   background: #fff;
   left: 12%;
   padding: 0 15px;
   position: relative;
   z-index: 5;
 }

Y escribe tu HTML así

<div class="d-flex flex-row align-items-center">
  <h1><span> Title </span> </h1>
</div>

0

Línea horizontal y vertical con palabras en el medio.

.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: red;
    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: red;
    display: block;
    width: 50%;
}


/*begin second box*/
.second{
    width: 300px;
    height: 100px;
    margin: 10px;
    border-width: 2px 0 2px 0;
    border-color: red;
    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: red;
    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>

Esto también se responde en https://stackoverflow.com/a/57279326/6569224


-1
  • Imagen pequeña creada 1x18 con un solo punto de color # e0e0e0
  • Transformó la imagen a código base64

Resultado:

body
{
  background: #c0c0c0;
}

#block_with_line
{
  width: 100%;
  position: relative;
  height: 18px;
  background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAASAQMAAACgmSb/AAAAAXNSR0IB2cksfwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAZQTFRFAAAA4ODg8vF4+wAAAAJ0Uk5TAP9bkSK1AAAAEElEQVR4nGNgQAMN6AIMDAAJpACBAQttyAAAAABJRU5ErkJggg==');
}

#block_with_line span
{
  background: #e4e4e4;
  width: 150px;
  display: block;
  margin: 0 auto;
  position: absolute;
  left: 50%;
  margin-left: -75px;
  text-align: center
}
<body>
  <div id="block_with_line">
    <span>text</span>
  </div>
</body>

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.