Position fixed element with percentage width relative to container
Asked Answered
I

2

10

I know that position: fixed makes an element relative to the viewport instead of it's offsetParent however I have an issue where I have a side element which takes x amount of space and then some fixed position heading elements which I want to take up a percentage of the remaining viewport width.

See fiddle: http://jsfiddle.net/U5DSZ/

Now I could put all the h1 element's into their own container but then they lose their semantic meaning as they are no longer associated with their content.

I understand JavaScript could do this but I am against using JavaScript for page structure.

Is there a way to do this in a purely HTML or CSS way? I don't mind moving the h1 element's as long as they retain their relationship with the content and the content remains statically positioned.

Ironist answered 3/6, 2013 at 15:28 Comment(11)
Is this what you are trying to do? jsfiddle.net/audetwebdesign/U5DSZ/1Ornithology
@MarcAudet Very close but I need the headers to take the remaining space after sidebar.Ironist
are you just wanting the headers to take up the remaining width of the screen or do you need them to go up and down the page too? If it's just the width thing then: jsfiddle.net/peteng/U5DSZ/2 (not sure what the value of it going up and down the page is)Mexico
Ok, just making sure, working on it... thanks for the quick feedback.Ornithology
@Mexico both, fixed positioning and take up the remaining space. It makes more sense in it's real context this is just a highly simplified demo I could easily reproduce.Ironist
@George, I don't think what you are wanting is possible with pure css. If you have the width, you will need js to move it up and down. Otherwise if you have it fixed, you will need js to calculate the correct width (until this css3 calc thing comes in)Mexico
just as an aside, this is how simple it would be to do it with a little bit of js jsfiddle.net/peteng/U5DSZ/4Mexico
@Mexico That's what I fear but sometimes you can do magical things with CSS.Ironist
@Mexico Indeed but I could do without the stutter.Ironist
@Mexico Your jQuery aided solution is worth posting. I have a CSS option that is pretty close so it would be good to have both approaches.Ornithology
@Mexico I did end up going down the JavaScript route but calculated their pixel positioning at runtime and set them to fixed so that they don't get repositioned twice on every scroll event (causing jitter), and just resize them on window resize. Thanks for your help.Ironist
O
7

You can get the effect that you want as follows.

Your HTML snippet is good as is:

<div id="content">
    <section>
        <h1>Heading 1</h1>
        <p>...</p>
    </section>
    <section>
        <h1>Heading 2</h1>
        <p>...</p>
    </section>
</div>

and the CSS is good but just requires some explanation:

#content {
    overflow: visible; /* default, but important to notice */
}

section {
    float: left;
    width: 25%;
}

h1 {
    position: fixed;
    width: 25%;
    background: #00FF00;
    text-align: center;
}

and the demo fiddle: http://jsfiddle.net/audetwebdesign/4zLMq/

How This Works

Your #content block takes up the remaining width to the right of your 200px left floated sidebar.

Within #content, you have two left-floated section elements that take up 25% of the parent container, which in this case, is the width of the view port panel.

Your child h1 elements have position: fixed, which means that their width of 25% is also computed based on the width of the viewport (not #content).

Case 1
If you want h1 and #content to have the same width, they need to have the same relative (25%) computed from the same containing block (view port in this case).

However, the value of 25% is not 25% of the remaining space after you account for the floated sidebar. However, maybe you can live with this.

Case 2
You could make the width values a bit easier to determine if you set the sidebar width to be a relative value. Using mixed units is always an issue.

Ornithology answered 3/6, 2013 at 16:7 Comment(2)
Thanks, I decided to go down the JavaScript route as I did require the width to take up the screen. However instead of using an onscroll event I calculate the position and pixel width and set them to fixed via JavaScript after load as it prevents them jittering and being repositioned twice on every scroll event. However this is a great answer so I will mark this as correct.Ironist
A jQuery/JavaScript aided solution makes sense here. Because of the mixed units (px and %), it is hard to determine the width remaining to the right of the floated element using CSS alone. It would be good to have the JS solution as part of this post. I have seen similar questions several times in the past few months so you are dealing with a fairly common problem. All the best!Ornithology
D
1

tldr; Shorter and cleaner solution:

h1 {
    width: inherit;
    ...

I stumbled upon this question, with a similar issue : my container's size can be user defined through resize:both (and moveable too!).

If I followed the accepted solution, it implied I had to apply the same props to my fixed header inside my container (top, left, width and height…).

Instead, inheriting the width from the parent container works properly. I found this way much simpler, and it makes more sense too, tested on major browsers and mobiles (demo).

Dewyeyed answered 24/7, 2017 at 9:52 Comment(1)
if you inherited a percentage width, it's relative to viewport instead of the parent node.Culmiferous

© 2022 - 2024 — McMap. All rights reserved.