I’m trying to achieve a specific layout which I’ve tried to show here: http://tmp.grytoyr.net/layout/
Basically I am trying to have multiple absolutely positioned elements with their own scrollbars. The challenge is to get the height of the elements correct, so that the scrollbars look natural. Another requirement is that left and right should always occupy 50% of the main content area.
In Chrome and Safari on Mac it works as expected, but in Firefox the scrollbars for the scrollable elements that have been pushed down by the headers (menu, left, right) extend below the viewport.
I am guessing this is because Firefox interprets height: 100% on an absolutely positioned element with some content above it a little differently than Webkit browsers do.
Is there any way to achieve the desired layout in all modern browsers?
Edit: I’ll answer my own question since I just figured it out.
I had added "box-sizing: border-box" which I thought Firefox supported by now, but it turns out I needed to add "-moz-box-sizing: border-box" too.
Edit2: But be sure to check out the answer by rgthree, since that is a much better way to achieve the layout I wanted.
Yes, you cannot use height of 100% in this case, as that will be the height of the container and you have additional elements/padding/offset that is contributing to your overflow.
For instance, if a container's height is set to 500px, and you have a child content element with a height of 100%, its height will also be 500px. But if you start that child element under another element that is 50px (say, like a header in your example), then the total height is 550px (50px header + 500px "100%" content).
What you can do for your example, since everything is layed out absolutely, is use top/right/bottom/left. Here's the concept:
/* The container -- height/width doesn't matter */
.container {position:relative; height:500px; width:500px;}
/* A 50px tall header -- notice no width is set, but left/right is set to 0 */
.container > .header {
position:absolute;
top:0px;
left:0px;
right:0px;
height:50px;
}
/* The content under the header -- notice no height or width is set */
.container > .content {
position:absolute;
top:50px; /* 50px top to be below the header */
left:0px;
right:0px;
bottom:0px; /* Bottom is 0 so it will stretch the rest of the height */
overflow:auto;
}
Now, just apply this technique to all your nested items and you'll be in business.
Related
Considering I aim modern desktop and mobile browsers, is there any practical difference in which one of the following css rules to use? Are there any hidden caveats?
.modal-1{
position:fixed;
top:0;
right:0;
bottom:0;
left:0;
}
.modal-2{
position:fixed;
width:100%;
height:100%;
}
.modal-3{
position:fixed;
min-width:100%;
min-height:100%;
}
And a sub-question: what if everything is the same, except position:absolute;, when I want to make a modal div inside another (relative or absolute positioned) div and not body, is there any difference in css rules then?
Based on your classes used with a div:
Using modal-1 seems not to add any margins at all and is fully responsive due to its nature.
modal-2 and modal-3 inherit parent margins in Firefox, not in Chrome though, body { margin: 0 0 0 0; } fixes it (in my test case body was the parent element.)
Using top, right, bottom, left appears to be the most fail-safe choice, in my opinion it's best used with #media (min-width:***px) query to help arrange the layers within the fixed container.
As for your sub-question, any child element (sub-modal) should best use position: relative and set itself within using top, left, width and height. You could also manipulate overflow in case of troubles.
I hope that answers your question(s).
your main container dive should have position:relative and if you want full screen width:100% and height:100% with display:block ...
for position children div inside parent they should have absolute position
I'm trying to create a content container in the middle of my site that can be no wider than a certain size (1194px), and will always have at least 242px margins on the left and right sides. If the container is wider than 1194px, the margins will grow. If the container is smaller than 1194px, the margins will stay 242px, shrinking the width of the container. Here's what I'm using and isn't working.
.mainContainer {
margin-left:242px;
margin-right:242px;
max-width:1194px;
}
But the container shrinks to fit the content. If I specify width:100%;, the margins will grow when the container is bigger than max, but the container will not shrink. What am I missing?
As a sub problem; I'm doing this in order to make my page responsive. Inside .mainContainer, there is a series of .projectContainer's, each 384px wide with 7px margin all sides. The width (including margins) of 3 of these adds up to the 1194px of .mainContainer. As of thus far, these values have been static. But now that .mainContainer is going to be fluid, I want the .projectContainer widths to also be fluid—as .mainContainer decreases in width, so should the .projectConatiner's.
My math figures that each .projectContainer, not including the 7px margin on each side, should be taking up 32.160804% of the .mainContainer:
384px * 3 = 1152px
1152px / 1194px = 0.96482412
0.96482412 / 3 = 0.32160804
Yet giving a value of width:32.160804%; to .projectConatiner doesn't seem to work. Is it a rounding error? How could I achieve what I'm looking for?
For the first problem:
see this fiddle
you can define the margin auto for the child div(width 1194 div), and min-width:1194+242+242=1678px for container,
this will make sure there is minimum margin of 242px on both sides, and when the page width increases the margin will increase(not the child width), and child remains 1194px only
<div class='container'>
<div class='child'>1194px</div>
</div>
.container{
min-width:1678px;
height:70px;
background:green;
}
.child{
background:red;
height:50px;
width:1194px;
margin:auto;
}
Use this buddy. No need for responsive css cause this is already responsive.
.mainContainer {
margin:0 auto;
max-width:1194px;
width:100%;
}
try using
#media screen and (max-width : 1194px) {
code css
}
for responsive style
Related questions do not contain helpful answers.
I'm trying to create a headerbar for a website that has a width of 2000 pixels (so wide enough to cover most large screens), but which is centered, but I also do not want the parent container div (which is positioned left 50%) to cause the browser to overflow horizontally.
I can't just "overflow hidden" on the html or body tags, as I am not declaring a specific width (and declaring 100% doesn't hide the overflow).
The code I have looks like this:
<body>
<div id="navbgout">
<div id="navbg"></div>
</div>
#navbgout {
width:2000px;
height:60px;
position:relative;
left:50%;
}
#navbg {
width:2000px;
height:80px;
position:relative;
left:-50%;
background-image:url("images/header_bg.png");
}
I've tried putting another parent container around it to provide an overflow:hidden, but nothing works. If I set that parent to 100% width, it doesn't mask. If I set it to a fixed value in pixels, it isn't reflexively sized.
This is particularly vexing as the iPad's mobile Safari will read this "overflow" width as true width and zoom the page out extra far to account for it.
You don't need to declare the width as 2000px to cater for screensizes. If you set the width as 100% then it will always adjust to the width of the viewport.
Ideally you would set the width as 100%, then add a container class with e.g. max-width: 1200px; and margin: 0 auto; This will then make the navbar always the width of the viewport but also allow the content to be centered on the screen.
I have decided to move over to percentages rather than fixed pixels in the hope of minimizing the input for a fully responsive website, but have already encountered and error. I am on the nav bar, and when testing how it looks, the text just overflows off the screen like nothing at all is stopping it! I don't know why I have tried : Putting it in a wrapper, Setting a max width, changing padding, Margin:0 auto;
#nav{
width:100%;
height:10%;
position:fixed;
background:#ccc;
padding-left:10%;
padding-right:10%;
}
From the looks of it the problem could be your height attribute. I'm assuming the text is spilling down the screen, not off the side of it?
Having a set height is usually a bad idea, especially as percentage heights can be quite irritating to work with. For example, inline elements take their percentage widths and heights from whatever is inside them. If that's the word "hello" then it's 10% of however much of the screen that word would take up.
With responsive design it's usually best to use a percentage for your width and just set height to "auto", or on most browsers you can just not put it in your CSS as "auto" is the default value anyway.
However, for a quick fix that'll stop text spilling out of the box, "overflow:hidden" will hide anything that flows outside of the element.
You should use box-sizing:border-box, so the total width of the box (including borders, margin and paddings will be 100%).
#nav{
width:100%;
height:10%;
position:fixed;
background:#ccc;
padding-left:10%;
padding-right:10%;
box-sizing:border-box;
}
If you don't use the border-box box-sizing, then the total width of the box will become the specified width + padding + margin + borders.
Read about the box model here: http://www.w3schools.com/css/css_boxmodel.asp
I'm trying to understand CSS positioning and I'm having trouble figuring out why a simple change that apparently should have no effect on the layout is causing a very disruptive change. I'm obviously missing something.
The initial objective was to place an inner div
vertically and horizontally within another div. That was fairly simple:
html, body {
margin:0;
padding:0;
height:100%;
}
div#container {
position:relative;
background:#4444ff;
margin: 0 auto; /* center, not in IE5 */
height:80%;
min-height:80%;
}
div#childDiv {
position:absolute;
background:#ff5555;
/* next we center it vertically and horizontally */
width:900px;
height:600px;
top:50%;
margin-top:-300px;
left:50%;
margin-left:-450px;
}
...and in the HTML page I used:
<body>
<div id=container>
<div id=childDiv>
test
</div>
</div>
</body>
which worked fine.
The curious part is what happens when I change the position attribute of the #childDiv div from absolute to relative.
My understanding is that first is should not affect the #container div at all since I'm changing only the position of the child element, and second that it should not change the layout since it is the only child element, its parent uses relative position and third I have not specified any offsets (tp, left, etc).
Instead, when I make this change, the parent #container is messed up (shows only up to the half of the viewport instead of 80% height as previously), and the position of #childDiv changes accordingly (also upwards, half outside the viewport).
My questions is: why does that happen? What concepts I'm not taking into account and why was the parent div affected by a change in the children's position setting?
If I remove #childDiv from within #container and place it inside body, then #container is no longer affected by that change so it seems something is propagating up in the DOM, which is odd to me. I've seen the same in firefox, opera, IE and chrome.
I have read W3C's spec on this topic but I haven't been able to figure this one out so far...
UPDATE: I created examples in JS fiddle to show the problem. You can see the original is here: jsfiddle.net/7Pr9y/1 and the affected one is here: jsfiddle.net/7Pr9y/3
Thank you!
Eduardo
When something is absolutely positioned, it is taken out of normal flow so its size, margins, etc. do not affect the things around it.
When something is relatively positioned, it is placed in normal flow (so its size, margins, etc. do affect the things around it) and layout is initially handled as if it were position: static, then it is moved according to the left, right, top and bottom properties.
It looks like your CSS got complex quickly because as soon as you positioned the child div absolutely, your container div would have disappeared, and putting percentage-based widths and heights on it wouldn't work.
The reason for this is that once you position something absolutely, it's taken out of the document flow, so your container div is now acting as if it contains nothing. If it contains nothing, unless you give it absolute dimensions (say, in pixels), you're saying "size yourself to a certain percentage of your container", which in this case, is the body element, which also acts as if it contains nothing.
When you start tossing heights and widths and min-heights on every element to compensate, especially when they are relative values, the results can become unpredictable very quickly. My advice would be to check out this reference on the box model by Chris Coyier: http://css-tricks.com/the-css-box-model/
It's super straightforward and uses some great diagrams to help visualize the different aspects of CSS positioning.
OK, I figured out why it becomes smaller when I change the size to relative.
Happens that because I have set the margins of the #childDiv to a negative value in order to center it, when I change it to relative that negative margin is taken into account when calculating the height of #container, resulting in a smaller #container.
I'm obviously a beginner in this, but seriously, it looks like CSS made it as complicated as possible to lay things out. No surprise most folks coming from table layouts start frustrated. :(
You don't need all these negative margin settings. Do the following:
html, body {
margin:0;
padding:0;
height:100%;
}
div#container {
background:#4444ff;
margin: 0 auto; /* center, not in IE5 */
text-align: center;
height:80%;
min-height:80%;
}
div#container:before {
content: '';
display: inline-block;
height: 100%;
vertical-align: middle;
margin-right: -0.25em; /* Adjusts for spacing */
}
div#childDiv {
display: inline-block;
text-align: left;
vertical-align: middle;
background:#ff5555;
width:500px;
height:200px;
}
I have used your code you provided and changed it around a little, to make the ghost spacer (the div#container:before) work.