Two elements of same height + absolutely positioned children - html

I have a website with a side-bar navigation and a main content pane, wrapped in a container element. The content has a background of its own, while the menu borrows that of the parent container.
In cases where the sidebar is longer than the content, I need the content element to stretch all the way down to cover the same height, so that the content background makes up the majority of the screen space to keep the design from looking silly.
This works beautifully by giving the container display: tableand both children display: table-cell. This will place them next to each other and ensure that they're always the same height.
However, now I want to have two lesser navigation bars in the content. One fixed to the top, one to the bottom of the pane. I use position: relative on the content and position: absolute on the nav bars to achieve this.
This solution works perfectly on modern browsers, but Firefox versions before 31 do not accept position: relative on table-cell elements, and the navbars are positioned relatively to the document body.
Can I somehow make this solution work on all common browsers? I need to maintain that the content element stretches down with the sidebar.
Links:
JSFiddle demonstrating the issue
Live website suffering the problem
A simplified code example:
div {
display: table;
width: 100%;
}
nav {
vertical-align: top;
display: table-cell;
width: 25%;
}
main {
display: table-cell;
position: relative;
}
main header,
main footer {
position: absolute;
}
main header {
top: 0;
}
main footer {
bottom: 0;
}
<div>
<nav>
Sidebar
</nav>
<main>
<header>
Top navbar
</header>
Content
<footer>
Bottom navbar
</footer>
</main>
</div>

According to this answer: https://stackoverflow.com/a/8312358/3929902, the only way to solve this is by adding a <div> around the elements displayed as table-cells, with position relative, like in this fiddle http://jsfiddle.net/qp7vhtk8/6/
In your example that just means adding:
div {
position: relative;
}

Related

Flexbox affected by margin afterwards

I am trying to create a simple web page with a navigation bar and a title centered in the page. However, the margin of the title div somehow affected the positioning of the navigation bar.
I think this is caused by the margin collapsing of two adjacent block-level boxes? I have tried to fix this problem by adding a <br> after the navigation bar, it worked, but I think it is not elegant.
Is there a better method to achieve what I want?
Below is my simplified HTML code:
<header id='navbar-bg'>
<div id='navbar'>
<ul>
<li>Foo</li>
<li>Bar</li>
</ul>
</div>
</header>
<div id='body'>
<h1 id='search-title'>This is a title</h1>
</div>
And the CSS style:
#navbar-bg {
position: fixed;
width: 100%;
}
#navbar {
display: flex;
align-items: center;
}
#body {
margin-top: 200px;
}
Since the position of #navbar-bg is fixed, I want the navigation bar as a whole to be fixed, and the margin-top of #body should not affect the navigation bar. Yet the margin-top moved both the #body and the navigation bar down, which is strange.
I want to fix this problem using an elegant solution, not adding a <br> after header.
You have to set a top: 0px to the #navbar-bg element. According to Mozilla:
The element is removed from the normal document flow, and no space is created for the element in the page layout. It is positioned relative to the initial containing block established by the viewport, except when one of its ancestors has a transform, perspective, or filter property set to something other than none (see the CSS Transforms Spec), in which case that ancestor behaves as the containing block. (Note that there are browser inconsistencies with perspective and filter contributing to containing block formation.) Its final position is determined by the values of top, right, bottom, and left.
So, when you don't use top for the #navbar-bg element, it will fall back to it's initial values, which is relative to body. So the body margin is also present in that element.
For a navbar it's probably best to be on the left of the body, so you could do this in your CSS:
#navbar-bg {
position: fixed;
width: 20%;
float: left;
}
#navbar {
display: flex;
align-items: center;
}
#body {
margin-top: 200px;
float: right;
width: 80%;
}

How do I position my footer to the bottom of the page, regardless of the size of viewport or the content?

My footer works perfectly on every page of my website, except the mobile version of my About page. On my About page, the content (headers, paragraphs, etc.) is larger than the height of the viewport, and for some reason, the footer sticks to the bottom of the viewport, but not the bottom of the page.
This is my website's About page. If you resize the size of the browser window to a width similar to a mobile device's, you should see what I'm talking about.
Here is my HTML structure (without the content):
<!DOCTYPE>
<html>
<head></head>
<body>
<div class="wrapper">
<header><nav></nav></header>
<section></section>
<footer></footer>
</div>
</body>
</html>
Here is the relevant CSS:
html,
body {
height: 100%;
}
.wrapper {
position: relative;
min-height: 100%;
}
footer {
position: absolute;
bottom: 0;
height: 40px;
width: 100%;
}
And one more weird thing that's happening that I can't explain...
If I go to my About page, resize the browser window's width to something more mobile, and go into the Chrome developer tools... and then I scroll down, past where the footer is (but shouldn't be) on the page, it looks like the <html>, <body>, and <div class="wrapper"> elements all end at where the footer ends on the page, even though the <section> content continues on down. It's like the content is overflowing out of the entire <html> element, and I have no idea why this would happen.
Also, I am aware of position: fixed and that it would easily fix this problem, but I would prefer not to have the footer visible in the viewport at all times. In cases where the content on the page takes up more space than the height of the viewport (necessitating vertical scrolling), I would like for the user to be able to scroll down and then come to the footer at the bottom of the page, not have it in their face at all times.
From inspecting your live site, all the elements in your .about .section-content div are floated. You can either remove the property from them or clear the floats.
I simply changed your wrapper css position to absolute and it put the footer to the bottom of the page as requested.
.wrapper {
position: absolute;
min-height: 100%;
}
If this screws around with the content layout in non-mobile views use media queries.
#media screen and(max-width:480px) {
.wrapper {
position: absolute;
min-height: 100%;
}
.about h2, .about p {
float:none;
}
}

div with inline-block not resizing

I have two elements, both with display: inline-block, and the parent has white-space: nowrap.
When the screen is resized, the div on the right side don't resize, like this.
I'm trying to make only the blue div resize.
Full source (jsfiddle)
The structure of the html is like this:
<div class="container">
<div class="header">...</div> <!-- red -->
<div class="aside">...</div> <!-- pink -->
<article>...</article> <!-- blue -->
</div>
Relevant css:
* {
box-sizing: border-box;
}
div.container {
margin: 0 auto;
max-width: 40em;
padding: 0;
white-space: nowrap;
}
div.container > * {
white-space: normal;
}
.aside {
display: inline-block;
max-width: 15em;
vertical-align: top;
}
.article {
display: inline-block;
max-width: 25em;
}
Old question, but for the sake of knowledge of anyone who reads this and also has the doubt:
What I've found is that setting position: relative on the .container
and position: absolute on the .article does what I want.
An absolute positioned element is positioned relative to the nearest positioned ancestor, where a positioned element means anything with a position property different to static, the default; if does not found any positioned element, uses the body element.
The absolute positioned elements, if has their width and heigth in auto, resizes to fit its content, and limits the maximun sizes by its positioned ancestor. You can check this putting a short string instead a large one: the element will shrink to the length of text. If you remove the positioning from div.container, the article (if still positioned absolute) will grow (depending on its content) to cover the space between previous element and body width.
And, related to the aforementioned and to add some utility to this delayed answer, a not-very-know bonus: if you define the right and left properties of a absoluted positioned element, and leave the width in auto, the element will cover the horizontal size between the right and left defined. This way you could put something like
article {
background-color: #a0f4ec;
display: inline-block;
position: absolute;
right: 0;
left: 30%;
}
div.aside {
background-color: #faf;
display: inline-block;
max-width: 15em;
width: 30%;
}
This trick also applies in a vertical sense, but with height, top and bottom properties.
There are a few ways to do it.
Method 1:
two divs the same line, one dynamic width, one fixed
Method 2 (negative margins)
http://alistapart.com/article/negativemargins
Unfortunately, Narxx's answers require the divs to be floated. I'm sure that's what you should do if you're building a real site, but in my case, I'm trying not to use it.
What I've found is that setting position: relative on the .container and position: absolute on the .article does what I want.
Simplified fiddle
If anyone can explain why, I'll mark it as an answer.

CSS Fixing divs in place and hiding overflows

So, I've been stuck with this problem for a while now and I can't seem to find a solution.
I'm trying to make a layout consisting of (for now) 4 different content areas like so:
What I'm trying to do
I'm trying to do the following things:
Simple explanation: Content should be the only scrollable thing on the page, with the footer following right behind it if content fits on the page, fixed on the bottom otherwise.
Detailed explanation:
Fix banner and mainMenu so that they never move when page is scrolled.
Make the content scroll with a page so that:
If the content (and footer) fit on a page, no scroll is displayed.
If the scroll is needed, content goes behind the banner (not being shown) and does not appear again above it.
If the scroll is needed, content can scroll until the bottom line of it and the footer are in the visible area.
The footer should do two things:
If content and footer fit on the page, footer should stick at the bottom of the content
Otherwise, footer should be fixed on the bottom.
What I have tried
Fixing banner,mainMenu and the footer are fixed using position: fixed (and positioned accordingly). Parent div has overflow: hidden (which doesn't seem to work).
<div id='main'>
<div id='banner'>banner</div>
<div id='mainMenu'>mainMenu</div>
<div id='content'>.. some long content ..</div>
<div id='footer'>footer</div>
</div>
And
#main {
width: 960px;
height: auto;
margin: 40px auto;
overflow: hidden;
}
#main #banner {
width: 960px;
height: 100px;
position: fixed;
}
#main #mainMenu {
width: 230px;
height: auto;
display: inline;
float: left;
position: fixed;
top: 140px;
}
#main #content {
width: 720px;
height: auto;
display: inline;
float: right;
margin-top: 100px;
}
#main #footer {
width: 960px;
height: auto;
clear: both;
position: fixed;
bottom: 0;
}
The Problem
Footer does not follow content if it fits within the area
Content overflows on the top of banner
I would really prefer to do this just in CSS (if possible) and as compatible as possible (IE7+, all other major browsers).
It's really getting frustrating now.. Any help would be appreciated.
There is no conceivable way I can think of that would solve your problem by just using css. Once you have set your elements to a fixed position they are out of the flow and thus your other elements cannot conform around them.
However I did find a solution by doing two different things. For the header issue I simply added another fixed element above the main banner and set it to the color of the background. This way the content will scroll behind it and look as if it is hidden. For the footer, I set up some javascript using jQuery to see if the content overflows or not. If it does then the footer's position is set to fixed, otherwise the position is set to relative.
You can check it all out here in this demo: http://jsfiddle.net/mrQGh/4/
To test out the javascript simply delete the text until there is no more overflow and run it again.

Scroll page content within specific area?

I'm designing a website which has fixed elements on the outer edges of a fixed-width layout. A div in the center is reserved for the content.
When the user scrolls, I want all of the content (besides said fixed outer navigation elements) to stay within the borders of that center element.
Here's a quick mockup of what I mean:
I could very easily set the overflow property of the center element to auto, and have everything remain inside. However, it's very important that a scroll bar not be present on the edge of that element.
Basically, I'm wondering how to either:
Restrict content to that area
(perhaps I could change the size and
positioning of the body element -- is
that allowed? -- and then position
the fixed elements outside of the
body.
Hide the scroll bar that appears
inside the div when using
overflow:auto
Any help would be greatly appreciated!
If possible, you should break your fixed position elements up into 4 separate sections (top, left, right and bottom). Then just make sure you pad you centre content area by their respective widths and heights so the content doesn't get overlapped:
HTML
<!-- 4 fixed position elements that will overlap your content -->
<div id="top"></div>
<div id="left"></div>
<div id="right"></div>
<div id="bottom"></div>
<div id="content">
<!-- Your content -->
</div>
CSS
html, body {
height: 100%;
}
#top, #left, #right, #bottom {
position: fixed;
left: 0;
top: 0;
z-index: 2;
background: red;
}
#top, #bottom {
width: 100%;
height: 20px;
}
#bottom {
top: auto;
bottom: 0;
}
#left, #right {
height: 100%;
width: 20px;
}
#right {
left: auto;
right: 0;
}
#content {
position: relative;
z-index: 1;
padding: 25px; /* prevent content from being overlapped */
}
You can see it in action here.
Also note the position: relative on the content area. This is so z-index works correctly and the content is displayed below the fixed sections.
If you care about IE6/7 support, you'll need to add a CSS expression fix to get fixed position working properly in those awesome browsers.