How is padding-top as a percentage related to the parent's width?
From CSS fluid layout: margin-top based on percentage grows when container width increases :
In CSS, all four margin: and padding: percentages are relative to the width ...even though that may seem nonsensical. That's just the way the CSS spec is, there's nothing you can do about it.
Straight from the horse's mouth:
'padding-top', 'padding-right', 'padding-bottom', 'padding-left'
Value: <padding-width> | inherit
Initial: 0
Applies to: all elements except table-row-group, table-header-group, table-footer-group, table-row, table-column-group and table-column
Inherited: no
Percentages: refer to width of containing block
Media: visual
Computed value: the percentage as specified or the absolute length
Percentages: refer to width of containing block
How is padding calculated when using percentage (%)?
TL;DR
The padding is calculated according to the parent's width
First, you should note that:
Percentage:
The percentage is calculated with respect to the width of the generated box's containing block [...] (source: w3c, emphasis mine)
This means the padding is calculated according to the parent element width (it's worth to note that in non flexbox layouts, padding top and bottom are also relative to the width of the containing block).
With box-sizing: border-box
When you change the default box-model to border-box, the padding (and border) is included in the width of the element like in your example. So with
width:600px;
padding-right:50%;
box-sizing:border-box;
The right padding must be 50% of parent's width but the overall width of element is 600px wide. The only moment the padding right is 50% of element's width is when parent width = element width
(Note that this can't happen in your example because the parent is body and body has a default margin).
Workaround:
If you want the padding to be 50% of the element's width, in this box model you can:
- set a fixed padding:
width:600px; padding-right: 300px;
- give the element a fluid width :
width:50%; padding-right:25%;
Without box-sizing: border-box
In the default box-model, the padding isn't included in the width of the element so element width = 600px + 50% of parent's width
as you can see in the following example:
#Test{ width:600px; padding-right:50%; background:#ddd;}
<div id="Test">TEXT ETISI DHOASIHD I SAIDUHSILAUDH LISH ADBHSJADB JHSA DKH ASKDH KSAH DKLJS ADLK ASJKLD KLASH DLSJAH KLS ADKL S JS KSH KD KSJ HDKJSH DKH SDKH SKDH KSJH DKJSH DKJ HTEXT ETISI DHOASIHD I SAIDUHSILAUDH LISH ADBHSJADB JHSA DKH ASKDH KSAH DKLJS ADLK ASJKLD KLASH DLSJAH KLS ADKL S JS KSH KD KSJ HDKJSH DKH SDKH SKDH KSJH DKJSH DKJ HTEXT ETISI DHOASIHD I SAIDUHSILAUDH LISH ADBHSJADB JHSA DKH ASKDH KSAH DKLJS ADLK ASJKLD KLASH DLSJAH KLS ADKL S JS KSH KD KSJ HDKJSH DKH SDKH SKDH KSJH DKJSH DKJ HTEXT ETISI DHOASIHD I SAIDUHSILAUDH LISH ADBHSJADB JHSA DKH ASKDH KSAH DKLJS ADLK ASJKLD KLASH DLSJAH KLS ADKL S JS KSH KD KSJ HDKJSH DKH SDKH SKDH KSJH DKJSH DKJ H</div>
Padding top as percentage of width not working
On MDN for padding :
Percentages refer to the width of the containing block [source]
This means percentage padding is calculated according to the width of the parent element, not the element itself.
In your case padding top for #container
is calculated according to the width of <body>
.
How to set the margin or padding as percentage of height of parent container?
The fix is that yes, vertical padding and margin are relative to width, but top
and bottom
aren't.
So just place a div inside another, and in the inner div, use something like top:50%
(remember position
matters if it still doesn't work)
How to calculate padding-top in % of the given div relative to its parent div
This is because padding
and margin
in %
gets calculated from width
, not height
as you desire.
From the spec for padding
Unlike margin properties, values for padding values cannot be negative. Like margin properties, percentage values for padding properties refer to the width of the generated box's containing block.
And from the spec for margin
The percentage is calculated with respect to the width of the generated box's containing block. Note that this is true for 'margin-top' and 'margin-bottom' as well. If the containing block's width depends on this element, then the resulting layout is undefined in CSS 2.1.
This is also how you can create aspect-ratio locked divs in HTML since you can calculateheight
fromwidth
usingpadding-top
with a percentage value.
A solution for you would be to use CSS calc, it has good browser support and fixes your issue in quite a simple manner. The only downside here is that it doesn't calculate the padding-top
in %
but you simply cannot calculate padding-top
in %
from the height
of the element unless you use javascript.
If you don't absolutely require the padding-top: 2%;
I would suggest the below solution.
Your CSS would look like this
ul.list li {
height: calc(10% - 8px);
padding-top: 8px;
}
This would give all ul.list li
items a height of 10% - 8px
and that 8px
is then also used as value for padding-top
which would basically make a perfect 10%
again.
You can write your selectors in a different style too, I used ul.list li
here as the main selector to just select all li
elements but you have :nth-child(odd)
and :nth-child(even)
selectors.
You wrote duplicate properties on these selectors while the only difference is their background
property.
I would strongly recommend to avoid duplication as much as possible as you'll definitely forget to change both properties sometimes, instead change your CSS to something like this:
/*shared properties in a general selector*/
ul.list li {
width: inherit;
height: calc(10% - 8px);
padding-top: 8px;
background: grey;
}
/*if rule is not applied, use ul.list instead of just ul*/
ul li:nth-child(even) {
background: red;
}
This even removes the need for ul li:nth-child(odd)
since this can also be part of the shared styling and then be overwritten by the more specific ul li:nth-child(even)
selector.
Another way
Another way of doing this instead of relying on %
values is to use either em
or rem
values - they work by scaling based on font size.
More reading
- web-design-basics-rem-vs-em-vs-px-sizing-elements-in-css
- the-ems-have-it-proportional-media-queries-ftw
- ems-rems
- confused-rems-ems
Basically, rem
is always relative to the root element
which is the <html>
element.
Setting a font-size on the <html>
element will define the value of 1rem
in CSS, if no font-size
is set then the browser default (usually 16px
will be used).
html {
font-size: 16px; /*1rem is now 16px*/
}
When you define the font-size
like above with a value of 16px
then 0.5rem
will equal 8px
- why is this interesting? It's scaleable! But by different means.
When you now apply a media query and change the font-size
to something bigger or smaller, everything using rem
will scale proportionally (you'd have to set font-size
of the <html>
element ofcourse.)
Now em
is a bit different, it's relative to it's own font-size
but since this get's inherited from it's parent element automatically (if font-size
is set in em
or %
that is) it's basically relative to the parent.
If we take the last CSS example
html {
font-size: 16px; /* 1rem = 16px, 1em = 16px */
}
body > div { /*every direct div of body tag*/
font-size: 0.5em; /*8px*/
font-size: 0.5rem; /*8px*/
}
body > div > div { /*every second level nested div*/
font-size: 0.5em; /*4px*/
font-size: 0.5rem; /*8px*/
}
Basically, since em
is sort-of relative to it's parent size the font-size decreases more when you scale in em
- this is potentially dangerous since if you change your structure and add a container that slightly reduces font-size on most of the page this could have a bigger effect than you think.
With that out of the way, technically em
and rem
are the best ways to scale padding
and margin
on elements according to the font-size
property.
An example for your container could look like this:
ul.list li {
height: 8%;
padding-top: 0.5rem; /*if font-size is 16px, this will be 8px*/
}
In terms of scalability this will work when you change the font-size to something else on a mobile device for instance.
It doesn't provide a solution to your question but it does provide an answer and your best alternative when talking about scalability, I hope this helps you in your quest for that :)
CSS padding-top: 100% uses width of parent?
Yes, you are correct about padding-top percent referring to the width. It is part of the W3 CSS Box model specifications:
http://www.w3.org/TR/CSS2/box.html#padding-properties
You will not be able to reference height with padding percentages. It will always refer to width. Sorry =(
How does padding-top: 100% work?
Your child div is filling parent in 100% width. Padding-top property in percent is determined by div width. So, your child is getting 100% width of parent (30%) and padding top 100% means 100% width of that element. The same applies to margin-top which is calculated by width.
Margin-top percentage not relative to parent
Vertical padding and margin are relative to the width of the parent. Top and bottom on the other hand are not.
Try to place a div inside another. Use the top property (for example: top: 25%) and make sure you specify a position (e.g. position: relative;)
I've forked and adjusted your code example to demonstrate what I mean: https://codepen.io/anon/pen/Yaqmva
top: 5%;
position: relative;
Setting child's height when parent's height is set via padding-top
use position
,padding
will only add space of aspect ratio - so you need to use position:a
to content to ignore this space and
bsoluteposition:relative
to parent to be able to position it as you intend
.container { width: 100%; height: 100%; /*margin: 5px;*/ position: relative; outline: 1px dotted green;}
.parent { position:relative; width: 50%; height: auto; outline: 1px solid black; }.parent:after { content: ''; display: block; clear: both; padding-top: 50%; /*15*/ }
.child { float:left; width: 40%; height: 40%; outline: 1px dashed red; }.content { position:absolute; width:100%; height:100%;}
<div class="container"> <div class="parent"> <div class="content"> <div class="child">Child</div> </div> </div></div>
Related Topics
Vertical and Horizontal Align (Middle and Center) with CSS
Any Way to Remove Ies Black Border Around Submit Button in Active Forms
Blocky Gradient Effect in CSS3
Good Rules for Setting Up Print CSS
Force Non-Monospace Font into Fixed Width Using CSS
How to Make This Header/Content/Footer Layout Using CSS
How to Zoom an HTML Element in Firefox and Opera
What Does .Container.\31 25\25 Mean in CSS
Css3 Transform Order Matters: Rightmost Operation First
Css-Only Sticky Table Headers in Chrome
Firefox Ignores Padding When Using Overflow:Scroll
Binding in Control with "Class" Attribute
The Use of /Deep/ and >>> in Angular 2
How to Use Vertical Align in Bootstrap
Icon Fonts Not Loading in Ie11
How to Check Which CSS Styles Are Being Used or Not Used on a Web Page