Search code examples
csspositionfrontendelementpixel

Behavior of top, right, bottom, left css values when using 'px' vs '%'


When using top, right, bottom, left css values, why am I able to use percentages sometimes, but other times I have to use pixels (px), or the element won't respond.

For example (on a given element):

top: 25% - doesn't respond

top: 150px - works

I usually will use percentages over pixels (px) to keep things responsive, but why do percentages (%) sometimes not work? In what scenarios do each work best? Thanks.


Solution

  • According to the WC3 specification for percentage units (<percentage>(ref)):

    Percentage values are always relative to another value, for example a length unit.

    A length unit (<length>(ref)) is a CSS data type that represents a distance value, or a value defined in relative (em) or absolute (px) length units.

    A percentage unit (<percentage>(ref)) is a CSS data type that represents a percentage value.

    Percentage units (e.g: top: 50%) used on nested elements won't apply if the containing element has no length unit (e.g: height: 200px) value defined, since percentage values are always relative to another value.
    This behaviour can be observed in the code snippet embedded below.

    Code Snippet Demonstration:

    .fixed-height {
        height: 200px;
        background: #4cbd2f;
    }
    
    .auto-height {
        background: #d04f38;
    }
    
    .nested {
        top: 50%;
        position: relative;
    }
    
    hr {
        border: 2px dashed #d4d4d4;
        margin: 25px 0px;
    }
    
    .fixed-height, .auto-height {
        padding: 10px;
        box-sizing: border-box;
        border: 2px dashed rgba(0, 0, 0, 0.3);
    }
    <h3>Fixed Height</h3>
    <h4><code>height: 200px</code></h4>
    <div class="fixed-height">
      <div class="nested"><code>top: 50%</code></div>
    </div>
    <hr>
    <h3>Auto Height</h3>
    <h4><code>height: auto</code></h4>
    <div class="auto-height">
      <div class="nested"><code>top: 50%</code></div>
    </div>

    Demonstrated in the code snippet above, percentage values will be dependent on length values. So although both nested elements have a top property of 50% declared, only the element nested in the containing element with a height property explicitly defined with length values will result in the expected behaviour.

    Note: Although <percentage> values are also CSS dimensions, and are usable in some of the same properties that accept <length> values, they are not themselves <length> values. ref


    Note: Only calculated values can be inherited. Thus, even if a percentage value is used on the parent property, a real value (such as a width in pixels for a <length> value) will be accessible on the inherited property, not the percentage value. ref