A `position:fixed` sidebar whose width is set in percentage?
Asked Answered
C

5

10

I've successfully used the beautiful Susy grid system to create a responsive layout similiar to the one of WebDesignerWall.com: enter image description here

What i failed to implement is a position:fixed sidebar.

Such a sidebar would not scroll when the page is scrolled and stays on the same place. That's fantastically convenient (anyway, you actually can't put more content into the sidebar, because it would clutter the top of page in a narrow window).

My layout goes crazy whenever i apply position:fixed to a column: enter image description here The colored blocks are declared three-column wide, but stretch further when position:fixed is applied to the sidebar..

I think the problem is that the width of the sidebar is relative, i. e. set in percentage. Due to position:fixed, the width is measured against the width of the browser window, not its container (though i set the container to position:relative).

The question is: how do i make a column fixed to the window while measuring its width against its container, not the viewport?

Maybe it's possible to fix the position of an element with JS?

PS I've tried the width: inherit solution, but it wasn't of any help to my situation.

Crypt answered 29/9, 2012 at 15:4 Comment(4)
I'd like to flag this question as there's no less than four answers which completely ignore the context of your question - namely, Susy - and instead offer unrelated solutions, but the question itself is great; how do I go about that? Or is it okay for crud answers to stack up if they're all sitting at 0? (Ironically, one answer says 'just use math!' - which is exactly what Susy does for you.)Need
tomeoftom, Why do you want to condemn the question? The question itself is perfectly valid and adheres to StackOverflow standards. The question has a great irrefragable answer (from the author of Susy!) that i was happy to mark accepted. It is a great reference for future use. I just don't get your point.Crypt
No, that's what I was saying! It's a fantastic question!Need
Edit: And has a perfect answer - I was trying to think of a way to remove the bad/irrelevant answers without offending you. I haven't flagged the question - I was wondering how best to draw mod attention without individually flagging every bad answer.Need
E
12

The way to do it is with a second container. I don't know your exact code, but here's an example. Let's assume your structure is something like this:

<div class="page">
  <header class="banner">
    <h1>header</h1>
  </header>
  <nav class="navigation">
    <ul class="nav-inner">
      <li>navigation link</li>
    </ul>
  </nav>
  <article class="main">
    <h2>main content</h2>
  </article>
  <footer class="contentinfo">
    <p>footer</p>
  </footer>
</div>

The only important assumption I made there was ensuring an extra wrapper around my navigation sidebar. I have both the <nav> tag and the <ul> tag to work with. You can use any tags you want, as long as the sidebar has two that can be used for structure - the outer for a fixed container, and the inner for the sidebar itself. The CSS looks like this:

// one container for everything in the standard document flow.
.page {
  @include container;
  @include susy-grid-background;
}

// a position-fixed container for the sidebar.
.navigation {
  @include container;
  @include susy-grid-background;
  position: fixed;
  left: 0;
  right: 0;
  // the sidebar itself only spans 3 columns.
  .nav-inner { @include span-columns(3); }
}

// the main content just needs to leave that space open.
.main { @include pre(3); }

// styles to help you see what is happening.
header, article, .nav-inner, footer {
  padding: 6em 0;
  outline: 1px solid red;
}

Cheers.

Electrolytic answered 30/9, 2012 at 5:22 Comment(7)
Thank you @eric-meyer, your solution is perfect! A small addition: a negative z-index should be applied to the fixed block, so that it wouldn't overlap main area making it unclickable.Crypt
Oh yes. Generally, if the only content of the fixed container is a float, that container should collapse and not cause any problems. But if it does cause problems, z-index is a great fix.Electrolytic
Hey Eric, the z-index solution fails in Chrome. The fixed column appears below the container and becomes unclickable in Chrome. :(Crypt
Okay, the solution is applying a positive z-index to the main column AND a relative position.Crypt
Yes, z-index only works on positioned elements. See: coding.smashingmagazine.com/2009/09/15/…Electrolytic
Setting the height of .navigation to 0 worked for me, and saves having to set any z-indices.Need
@tomeoftom That height: 0; idea works perfectly, thank you :) (oh, and thank you to everyone else that has contributed towards this idea, it's working perfectly for my new build)Cyril
H
1

You can't, fixed-position elements are detached from their containers, position: relative or no position: relative. Just set its width to an absolute value - it looks like your content is always 760 pixels wide, right?

Houphouetboigny answered 29/9, 2012 at 15:8 Comment(6)
This is the 3rd answer here that ignores the context of the question - the Susy grid system.Need
@tomeoftom: Isn’t that kind of like saying JavaScript isn’t a valid answer to a jQuery question? :|Houphouetboigny
Not at all. Sass does things physically impossible in CSS. The kind of grid layout Susy enables would mean you have to recalculate and reenter individual width percentages for every element on-screen for every change in layout. It's unfortunate that we can't rely on flexbox yet but until then Susy is one of the best ways we have of properly abstracting style from markup. Conversely, jQuery is a library built in Javascript - you can always recreate components of it.Need
@tomeoftom: I’m not huge on CSS preprocessors, but it’s a CSS preprocessor, not a magic browser-supported style system. So not really physically impossible. Anyway, this is still correct — setting its width to an absolute value is fine to do using a Sass mixin or not.Houphouetboigny
This discussion is getting a bit pointless. CSS can't do custom math. That's the "magic". That's why this question is framed within the context of Susy, because the author, I presume, doesn't want to have to crack out a calculator to figure out the exact column and gutter width every time they adjust the grid proportions.Need
@tomeoftom: Okay, so use a Sass mixin instead of 760px. I agree. What is the point of this discussion?Houphouetboigny
S
1

Maybe it's possible to fix the position of an element with JS?

Yes, but it will be tedious and isn't the ideal solution .

Instead, calculate the appropriate width using JavaScript and assign it, instead of using the percentage directly in CSS. Here's a basic outline:

function updateSize() {
    var outer = document.getElementById("outercontainer"); //get the container that contains your sidebar
    var navcol = document.getElementById("navcol"); //get the sidebar (which is supposed to have position: fixed;)
    navcol.style.width = Math.floor(outer.offsetWidth * 45/100) + "px"; //or whatever your percentage is
}
updateSize();
window.onresize = updateSize; /*make sure to update width when the window is resized*/

Note: the IDs used above are just placeholders -- you will need to modify them to fit your actual page.

Seven answered 29/9, 2012 at 15:31 Comment(0)
C
-1

Why don't you just use math? =)

Example html:

 <div class="container">
    <div class="col">
        <div class="fixed">This is fixed</div>
    </div>
</div>

CSS

.container {
    width: 80%;
    margin: 0 auto;
}

.col {
   float: left;
    width: 33.3333333333%;
}

.fixed {
    position: fixed;
    width: 26.666666666%; /* .container width x .col width*/
}
Charlotte answered 29/9, 2012 at 17:0 Comment(0)
A
-1

position:fixed works like position:absolute so it isn't positioned in relation of its container. It simply floats into your document. A quick fix would be something like this:

<div id="fixed-element" style="width:30%"> /* 30% of the document width*/
lorem ipsum dolor sit amet
</div>

<div id="faux-sidebar" style="width:30%; display:block"> /* 30% of the document, leave it empty, so it acts like a placeholder for the fixed element*/
&nbsp;
</div>

<div id="the-rest" style="width:70%"> /* the rest of the website goes here */
more lorem ipsum than ever before
</div>
Ashien answered 29/9, 2012 at 17:4 Comment(1)
I'm not sure this answer is in reference to SusyNeed

© 2022 - 2024 — McMap. All rights reserved.