Este é um Q antigo, mas uma solução moderna sem flexbox ou posição absoluta funciona assim.
margin-left: 50%;
transform: translateX(-50%);
.outer {
border: 1px solid green;
margin: 20px auto;
width: 20%;
padding: 10px 0;
/* overflow: hidden; */
}
.inner {
width: 150%;
background-color: gold;
/* Set left edge of inner element to 50% of the parent element */
margin-left: 50%;
/* Move to the left by 50% of own width */
transform: translateX(-50%);
}
<div class="outer">
<div class="inner">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Quos exercitationem error nemo amet cum quia eaque alias nihil, similique laboriosam enim expedita fugit neque earum et esse ad, dolores sapiente sit cumque vero odit! Ullam corrupti iure eum similique magnam voluptatum ipsam. Maxime ad cumque ut atque suscipit enim quidem. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Excepturi impedit esse modi, porro quibusdam voluptate dolores molestias, sit dolorum veritatis laudantium rem, labore et nobis ratione. Ipsum, aliquid totam repellendus non fugiat id magni voluptate, doloribus tenetur illo mollitia. Voluptatum.</div>
</div>
Então, por que isso funciona?
À primeira vista, parece que deslocamos 50% para a direita e depois 50% para a esquerda novamente. Isso resultaria em turno zero, e daí?
Mas os 50% não são os mesmos, porque o contexto é importante. Se você usar unidades relativas, uma margem será calculada como porcentagem da largura do elemento pai , enquanto a transformação será de 50% em relação ao mesmo elemento.
Temos essa situação antes de adicionarmos o CSS
+-------------------------------------------+
| Parent element P of E |
| |
+-----------------------------------------------------------+
| Element E |
+-----------------------------------------------------------+
| |
+-------------------------------------------+
Com o estilo adicionado margin-left: 50%
, temos
+-------------------------------------------+
| Parent element P of E |
| |
| +-----------------------------------------------------------+
| | Element E |
| +-----------------------------------------------------------+
| | |
+---------------------|---------------------+
|========= a ========>|
a is 50% width of P
E os transform: translateX(-50%)
turnos de volta para a esquerda
+-------------------------------------------+
| Parent element P of E |
| |
+-----------------------------------------------------------+
| Element E | |
+-----------------------------------------------------------+
|<============ b ===========| |
| | |
+--------------------|----------------------+
|========= a =======>|
a is 50% width of P
b is 50% width of E
Infelizmente, isso funciona apenas para centralização horizontal, pois o cálculo da porcentagem da margem é sempre relativo à largura. Ou seja, não apenas margin-left
e margin-right
, mas também margin-top
e margin-bottom
são calculados em relação à largura.
A compatibilidade do navegador não deve ser problema:
https://caniuse.com/#feat=transforms2d