CodeinWP CodeinWP

Vertical Percentages in CSS

Vertical Percentages in CSSI don’t think this happens very often. To be honest, I don’t think I’ve ever used a percentage value on a top padding/margin, or a bottom padding/margin value. Even for height values, I may have used a 100% value for a hack, but nothing else.

Nonetheless, using percentages on those vertical parts of a page are somewhat different in the way they are calculated, compared to other properties that take percentage values.

Here are the rules for percentages on vertical items:

  • A percentage value on top/bottom padding or margins is relative to the width of the containing block
  • A percentage value on height is relative to the height of the containing block (same for min/max height)
  • A Percentage value on top and bottom values for a positioned element is relative to the height of the containing block (hat tip to Hashem Qolami for the reminder)
  • Percentage values are not allowed on border widths (not even left and right)

And here’s a CodePen showing this in action, using top/bottom padding/margins set with percentages, along with a set-width container:

See the Pen Vertical Percentages by Louis Lazaris (@impressivewebs) on CodePen

Notice it uses jQuery to calculate and display the total height of the element including padding. I’ve intentionally used a value of 1000px for the container and 100×100 for the element itself, just to make any percentage calculations simpler to envision.

As it stands, the total height is 300px — which is 100px (as defined in the CSS) plus 100px of top padding (which is 10% of 1000px of the container width) and 100px of bottom padding (same calculation as top).

And keep in mind that the calculations would be vastly different if I just threw some content in the boxes and let the container element expand without a set width. Then the container’s width would be dependent on the window size (or iframe size, in the case of a code embed like above).

Also, if I was using box-sizing: border-box, that would affect the total height value that’s displayed.

Why Relative to Container Width?

In thinking about why vertical padding and margin percentage values are relative to the containing block’s width, my guess would be that this is simply much easier to control.

Width values are commonly set, whereas heights are usually just dependent on content. In fact, I would go as far as to say it’s usually bad practice to define a height on an element (min-height is fine though). So if you want to actually set vertical margin/padding percentages, it would be unintuitive to set these relative to an arbitrary content-based height. Instead, it’s much easier to do the calculation based on width — because it’s much more likely that a width is being set explicitly.

Of course, I don’t know if this is the case. I can’t seem to find an explanation for this anywhere, so if anyone who works on the specs has a more technical answer, then please comment and I’ll update the article accordingly.

These links on my CSS Values reference have external links to MDN and W3C, so you can look those up to see what the spec says:

23 Responses

  1. Šime Vidas says:

    The first two list bullets can be combined into one:

    «A percentage value on top/bottom padding or margin is relative to the width of the containing block»

    DRY FTW!

  2. Navaru says:

    Thank you!

  3. If vertical paddings and margins will be respective to containig box height then there will not be appropriate way to calculate height of containing box. If vertical paddings and vertical margins will grow then height of containing box will grow and vice versa.

  4. Thierry’s tweet adds some good info to this:

    I had forgotten about that method, and it’s quite relevant to this discussion.

  5. Thanks Louis for this topic; I expected you to cover top and bottom properties for positioned elements as well.

    • That is a good point. That’s interesting, as there seems to be some quirky behaviour on that. I might post a follow-up on this after I research it. Thanks!

      Edit: I’ve updated it. Looks like a simple line added to the “rules” list is enough. One thing I noticed is that if you use a min-height value on the container element, the top/bottom positioning value will not work with a percentage. But it will work with a height value (which is not great).

      • Hi Louis. Thanks for the update.
        But about the min-height issue, that’s weird, because it (% on top/bottom) works even you’ve used min-height on the container; At least in my test case: http://jsbin.com/imOWAnI/1

        • This is actually getting interesting, because I think I’ve tracked down a bug in one or more browsers.

          What you showed is true, but don’t forget that top/bottom values work on relatively positioned elements, regardless of positioning contexts. Here is a fork of your example:

          http://jsbin.com/axAkAQol/1/edit

          Notice the min-height value, and the percentage for the “top” property on the child, which isn’t working. Notice also there is no “relative” context on the parent, and the child is positioned relatively, not absolute. If you change the min-height to “height”, you’ll see that the “top” value will then take effect.

          This behaviour is present in latest stable Chrome (and Canary), latest stable Firefox, IE10, and Safari (all tested on OSX and Windows).

          Strangely, the only browser that has what seems to be the correct behaviour is Opera 12.16 (latest stable, still using the Presto engine, not Blink).

          Maybe there’s something about positioning and percentages that I’m not understanding here, but it would seem that the percentage value should still take effect in that example, but it doesn’t. Opera seems to be the only one doing it right. Any thoughts on this?

          After I post this comment, I’m going to submit a bug report with Chrome and FF and see if someone has a response.

        • It’s a known bug on Chrome:

          https://code.google.com/p/chromium/issues/detail?id=72416

          There is a very old similar bug report on this for Firefox that was labelled ‘invalid’:

          https://bugzilla.mozilla.org/show_bug.cgi?id=2992

          which someone has tried to have re-opened at some point, but I decided to create a new one:

          https://bugzilla.mozilla.org/show_bug.cgi?id=939641

          If Opera’s behaviour is wrong, then I guess it won’t matter. They’re using WebKit/Blink now so eventually all browsers will treat this the same way.

          • I searched the spec to find something have explained this behavior, but no success! there are some rules about top, min-height calculation for positioned and/or none-positioned elements.
            But none of them have mentioned that using these properties at the same time would have what behavior in different contexts.

            Just found another bug report here:
            https://bugzilla.mozilla.org/show_bug.cgi?id=260348

            The issue is using absolute positioning on the child, doesn’t need the parent to have specified height; But for relative positioned elements, it does :|

  6. Kevin Lorenz says:

    Even if I never thought about setting padding or margin top/bottom in % this is kinda interesting. Thanks for your post and the codepen.

  7. Patrick says:

    I worked with that a while ago for styling day CSS Day Logo (http://www.netzaffin.de/really-the-cssday-logo-shouldnt-be-an-image/)

    Yep, I was really confused until Eric Meyer refered me to the specs.

  8. Francky says:

    Hi Louis,
    Interesting matter! This article was mentioned in the “This week in CSS” (http://www.sitepoint.com/forums/showthread.php?1179755-This-Week-in-CSS) sticky of the Sitepoint Forum, that was how I came here.

    After some experiments I made the illustration page “Vertical percentage margins, some experiments and backgrounds” (http://clba.nl/sitepoint/vertical-percentage-margins.htm), an online testpage with notes about browser differences.

    My main conclusion about the “Why?” of using the Width of an element for computing the vertical percentages: the supposed W3C “principle of equal distances”. If only 1 margin/padding value is given, then all margins/paddings of a box should be the same in absolute value. – I didn’t find this principle in the specification, maybe I searched in the wrong place.

    But it is not always the Width, is said by css3: only in the “horizontal reading languages”. In “vertical reading languages” (e.g. a number of Chinese languages) all boxes are 90 degrees rotated, and then the Height has to be the starting point for the equal margins/paddings!

  9. Best Wigs says:

    Hi,
    Very new concept. but easy to do.Thanks for this technique.

    Thanks

  10. Elmira says:

    Cool trick. It’s one of the trick that I’m sure not lots of designer are familiar with.

  11. Neat trick. Thanks!

  12. Martin says:

    Old thread. but anyhow.
    The main concern about all limits and so is really to blame for that html/css is both old and poorly in all aspects.

    I am a web developer, and of course I am proud of solving problems in every day of my life.
    Vertical margins in percentage would be really cool, becasue in fluid layouts the margins between blocks/elements are changed based on the containing width, it would be cool to have a good way with dealing with the vertical margins in the same way.

    For example in a grid, in which the horizontal margins changes, so should the vertical margin do as well. Sure, minor design details might not be “that” important ;) But anyhow.. sure.. a solutions is always to be found.. “uhmn, you can use jQuery to follow the horizontal margin when it changes and allow jquery to update the vertical margin and so on and so..

    Yeah. html/css is cool.. astonishing sites could be done – cutting edge and experimental sites are also cool.. but yeah..

  13. BevSDC says:

    Great article. You should have share links on your articles so others can easily share them on Twitter, Facebook, etc.

  14. David López says:

    I forgot to mention, two specially important features of this article:
    1. The author TRIES TO UNDERSTAND WHY did the first authors wrote the specification in such a way, and tries to see if there’s a good reason, instead of what I wrongly did, of first saying: “they committed a mistake”. His attitude was FIRST trying to understand WHY. I find this great.

    2. The fact that he says WHEN can we trust that a percent dimension will be based on container’s HEIGHT, and when NOT, in the list at the beginning.

    I found those two details the best features of the article.

    Regards
    from Bogotá, Colombia
    David López
    Investigación y Programación

Leave a Reply

Comment Rules: Please use a real name or alias. Keywords are not allowed in the "name" field and deep URLs are not allowed in the "Website" field. If you use keywords or deep URLs, your comment or URL will be removed. No foul language, please. Thank you for cooperating.

Markdown in use! Use `backticks` for inline code snippets and triple backticks at start and end for code blocks. You can also indent a code block four spaces. And no need to escape HTML, just type it correctly but make sure it's inside code delimeters (backticks or triple backticks).