El elemento no permanecerá centrado, especialmente al cambiar el tamaño de la pantalla

Resuelto R. Bright asked hace 8 años • 2 respuestas

Mi problema es que no puedo centrar horizontalmente un puntero triangular.

Bueno, puedo centrar el puntero para algunos tamaños de ventana, pero cuando reduzco o extiendo la ventana, la coloca nuevamente en el lugar equivocado.

¿Qué me estoy perdiendo?

body {
  background: #333333;
}
.container {
  width: 98%;
  height: 80px;
  line-height: 80px;
  position: relative;
  top: 20px;
  min-width: 250px;
  margin-top: 50px;
}
.container-decor {
  border: 4px solid #C2E1F5;
  color: #fff;
  font-family: times;
  font-size: 1.1em;
  background: #88B7D5;
  text-align: justify;
}
.container:before {
  top: -33px;
  left: 48%;
  transform: rotate(45deg);
  position: absolute;
  border: solid #C2E1F5;
  border-width: 4px 0 0 4px;
  background: #88B7D5;
  content: '';
  width: 56px;
  height: 56px;
}
<div class="container container-decor">great distance</div>
Expandir fragmento

R. Bright avatar Apr 24 '16 05:04 R. Bright
Aceptado

Tienes tu flecha centrada con left:48%. Esto posiciona la flecha cerca del centro del contenedor según el borde izquierdo del elemento de flecha.

En otras palabras, supongamos que usó left:50%(que es la forma correcta de hacerlo), esto no centra el elemento de flecha en el contenedor. En realidad, centra el borde izquierdo del elemento en el contenedor.

En la imagen de abajo, un marcador está centrado en la página usando text-align:center.

A modo de comparación, vea la flecha centrada con left:50%.

ingrese la descripción de la imagen aquí

El elemento está colocado en el centro-derecha. Esta desalineación se vuelve más notoria a medida que la ventana se hace más pequeña.

Como resultado, es común ver que elementos centrados y absolutamente posicionados utilicen la transformpropiedad:

.triangle {
   position: absolute;
   left: 50%;
   transform: translate(-50%,0);
}

La transformregla le dice al triángulo que se desplace hacia atrás el 50% de su ancho. Esto lo hace perfectamente centrado en la línea. Ahora emula text-align:center.

ingrese la descripción de la imagen aquí

En translate(-50%,0), el primer valor apunta al eje x (horizontal), el otro se aplica al eje y. Una regla equivalente sería transform:translateX(-50%)(también existe transform:translateY()).

Además, aquí se explica cómo centrar un elemento tanto horizontal como verticalmente usando este método:

.triangle {
   position: absolute;
   left: 50%;
   top: 50%;
   transform: translate(-50%,-50%);
}

Nota: Si estuviera usando right: 50%o bottom: 50%, los translatevalores respectivos serían 50%(no negativos) .

Sin embargo, en esta pregunta en particular surge un problema porque transform:rotate(45deg)también está en el bloque de declaración. Agregar un segundo transformsignifica que el primero se ignora (según la cascada).

Entonces, como solución, prueba esto:

.container::before {
    left: 50%;
    transform: translate(-50%,0) rotate(45deg);
}

Al encadenar funciones, se pueden aplicar múltiples funciones.

Sólo tenga en cuenta que el orden importa. Si translatey rotatese invirtieran, el triángulo primero rotaría 45 grados y luego se desplazaría -50% a lo largo del eje rotado , rompiendo el diseño. Así que asegúrese de que eso translatevaya primero. (Gracias @Oriol por señalar esto en los comentarios).

Aquí está el código completo:

body {
    background: #333333;
}

.container {
    width: 98%;
    height: 80px;
    line-height: 80px;
    position: relative;
    top: 20px;
    min-width: 250px;
    margin-top: 50px;
}

.container-decor {
    border: 4px solid #C2E1F5;
    color: #fff;
    font-family: times;
    font-size: 1.1em;
    background: #88B7D5;
    text-align: justify;
}

.container::before {
    top: -33px;
    left: 50%;
    transform: translate(-50%,0) rotate(45deg);
    position: absolute;
    border: solid #C2E1F5;
    border-width: 4px 0 0 4px;
    background: #88B7D5;
    content: '';
    width: 56px;
    height: 56px;
}
<div class="container container-decor">great distance</div>
Expandir fragmento

jsFiddle

Michael Benjamin avatar Apr 23 '2016 22:04 Michael Benjamin

Podrías utilizar la nueva calc()función CSS3 que te permite hacer aritmética para determinar el punto central.

Para obtener su punto central, el cálculo deberá ser:

50% - (56px / 2)

Entonces esto termina siendo

50% - 28px

Poner esto en la calc()función debería resolverlo dentro del navegador y colocarlo perfectamente en el centro.

body {
  background: #333333;
}
.container {
  width: 98%;
  height: 80px;
  line-height: 80px;
  position: relative;
  top: 20px;
  min-width: 250px;
  margin-top: 50px;
}
.container-decor {
  border: 4px solid #C2E1F5;
  color: #fff;
  font-family: times;
  font-size: 1.1em;
  background: #88B7D5;
  text-align: justify;
}
.container:before {
  top: -33px;
  left: calc(50% - 28px);
  transform: rotate(45deg);
  position: absolute;
  border: solid #C2E1F5;
  border-width: 4px 0 0 4px;
  background: #88B7D5;
  content: '';
  width: 56px;
  height: 56px;
}
<div class="container container-decor">great distance</div>
Expandir fragmento

Stewartside avatar Apr 25 '2016 08:04 Stewartside