Why does "left: 50%, transform: translateX(-50%)" horizontally center an element?
I recently refactored some of my CSS and was pleasantly surprised to find an easier way to horizontally align my absolutely positioned element:
.prompt-panel {
left: 50%;
transform: translateX(-50%);
}
This works great! Even if my element's width is auto. However, I do not understand what's going on to make this actually work. My assumption was that translateX was just a modern, more performant means of moving an element around, but that does not appear to be the case.
Shouldn't these two values cancel each other out? Furthermore, why does
.prompt-panel {
left: -50%;
transform: translateX(50%);
}
not show the same result as the first code snippet?
Solution 1:
The CSS left
property is based on the size of the parent element. The transform
property is based on the size of the target element.
Name: transform
Percentages: refer to the size of bounding box [of the element to which the style is applied]
http://www.w3.org/TR/css3-transforms/#transform-property
'top'
Percentages: refer to height of containing block
http://www.w3.org/TR/CSS2/visuren.html#position-props
If the parent is 1000px wide and the child is 100px, The browser would interpret the rules in your question as:
Example 1:
.prompt-panel {
left: 500px;
transform: translateX(-50px);
}
Example 2:
.prompt-panel {
left: -500px;
transform: translateX(50px);
}
Solution 2:
left 50%
will move the element exactly at the center of the main container where this element belongs!
BUT translateX(50%)
will move the element right exactly to 50% of its width,and NOT at the center of the whole Container element!
Thats the main difference between them and thats why this example has differences!
A general example to clear this out: (fiddle here):
#pos
{
border:1px solid black;
position:absolute;
width:200px;
height:150px;
}
#pos-2
{
border:1px solid black;
position:absolute;
width:auto;
height:150px;
}
.prompt-panel {
position:absolute;
}
.prompt-panel1 {
position:absolute;
left: 50%;
}
.prompt-panel2 {
position:absolute;
left: -50%;
}
.prompt-panel3 {
position:absolute;
transform: translateX(-50%);
}
.prompt-panel4 {
position:absolute;
transform: translateX(50%);
}
.prompt-panel5 {
position:absolute;
left: 50%;
transform: translateX(-50%);
}
.prompt-panel6 {
left: -50%;
transform: translateX(50%);
}
#pos-auto
{
position:absolute;
}
<div><b> With fixed width 200px</b></div>
<br/>
<div id="pos">
<div class="prompt-panel">panel</div>
<br/>
<div class="prompt-panel1">panel1</div>
<br/>
<div class="prompt-panel2">panel2</div>
<br/>
<div class="prompt-panel3">panel3</div>
<br/>
<div class="prompt-panel4">panel4</div>
<br/>
<div class="prompt-panel5">panel5</div>
<br/>
<div class="prompt-panel6">panel6</div>
</div>
<br/><br/><br/> <br/><br/><br/><br/><br/><br/>
<div><b> With fixed width auto</b></div>
<br/>
<div id="pos-2">
<div class="prompt-panel">panel</div>
<br/>
<div class="prompt-panel1">panel1</div>
<br/>
<div class="prompt-panel2">panel2</div>
<br/>
<div class="prompt-panel3">panel3</div>
<br/>
<div class="prompt-panel4">panel4</div>
<br/>
<div class="prompt-panel5">panel5</div>
<br/>
<div class="prompt-panel6">panel6</div>
</div>