I'm learning CSS and got stuck creating a layout that contains a header and an image that fills the rest of the screen. Using the following code, I'm able to achieve what I'm looking for:
html, body {
height: 100%;
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.image-container {
flex: 1;
}
img {
width: 100%;
height: 100%;
object-fit: contain;
}
<html>
<body>
<div class="container">
<div class="header">
<h1>Test Page</h1>
</div>
<!-- <div class="image-container"> -->
<img src="https://picsum.photos/500/300"/>
<!-- </div> -->
</div>
</body>
</html>
Now the problem is that I want to wrap the image element into a div as I'd like to position an overlay on top of the image. As soon as I nest the img within a div, the resizing doesn't work properly anymore. If the screen is wide, the image overflows to the bottom, creating a vertical scrollbar.
I've tried a lot of things, but nothing's worked so far. Can you explain to me why introducing the div (image-container) changes the layout and how to make it behave like the version without the div? That'd be great, thanks in advance!
EDIT:
I want the image to be displayed exactly like in the snippet I posted. It should be as large as possible, but only so large that the whole image is still visible and nothing is cropped. For a wide window, there should be blank bars left and right of the image. For a narrow but tall window, there should be blank bars above/beyond the image.
My issue is that as soon as I add the <div class="image-container">, the image always takes the whole width. For a wide window, I get scrollbars and can't see the whole image anymore. I'd like to know how I can get the image to scale like in the version without the additional <div>. I'd also like to understand why adding the <div> changes how the image is scaled.
EDIT 2:
Someone suggested to add overflow: hidden; on .image-container, but deleted their answer. This does in fact work (overflow: hidden/scroll/auto; work, overflow: visible; does not), but now I'm completely confused to why that's the case. I thought that overflow would control if overflow is visible, but wouldn't affect the size of the content being displayed. In this case though, it seems like the overflow property does have an effect on the size of the picture being displayed. That's weird and if anyone knows what's going on, please let me know!
Flex is already helping the image take up as much space as possible, so the height: 100% and width: 100% were causing the image to grow.
For getting something to appear on top of the image, I would recommend looking into position: absolute or position: relative
html,
body {
height: 100%;
margin: 0;
}
.container {
display: flex;
flex-direction: column;
height: 100%;
}
.image-container {
display: flex;
justify-content: center;
}
img {
object-fit: contain;
}
<html>
<body>
<div class="container">
<div class="header">
<h1>Test Page</h1>
</div>
<div class="image-container">
<img src="https://picsum.photos/500/300" />
</div>
</div>
</body>
</html>
I have a relatively simple skeleton for a 1-page site.
The header area I'd like to stay put which I accomplished (at least in Chrome and my smartphone's native browser) by setting overflow:hidden on the overall container, then setting overflow:scroll to the scrollable area.
But then I went to double check this on FireFox and basically ran into all sorts of issues. Troubleshooting resulted in a mind-numbing amount of things falling out of place.
<div id="mainBlock">
<div id="tabContent">
<div id="one">
<h1>one</h1>
</div>
<div id="two">
<h1>two</h1>
</div>
<div id="three">
<h1>three</h1>
</div>
<div id="four">
<h1>four</h1>
</div>
</div>
<div id="bottomBlock">
<div>hellow</div>
</div>
</div>
with these styling rules
#mainBlock {
overflow-y: scroll;
margin: 0;
padding: 0;
width: 100%;
display: flex;
flex-flow: column;
align-content: center;
align-items: center;
}
#tabContent {
height: 100%;
width: 100%;
}
#tabContent > *{
height: 500px;
}
#bottomBlock {
background-color: #444;
height: 24px;
width: 100%;
}
When working, this results in the head area staying put while allowing for the rest of the content to scroll, with bottomBlock appearing at the end of the scrollable area.
However, in firefox, while scrolling is possible bottomBlock is stuck at end of initial viewport. As in if the viewport height is 900px, bottomBlock is seemingly absolute positioned at 901px.
If I move bottomBlock to within tabContent, then it works as it should.
But this issue has given me far too great of a headache to simply let it go.
I'm not sure how to make a fiddle of this, since the scroll bar is the main issue here, and fiddle's render box also has one.
Any help is greatly appreciated!
It works for me in firefox 45.0.1 if you remove the height:100% from #tabContent completely. What do you need it for? As the last block element #bottomBlock will always be on the very bottom.
Maybe it's a wierd css overriding/priority issue. I could imagine FF can't calculate the overall content height correctly because of the competetive #tabContent > * and #bottomBlock selectors.
Did you also try making tabContent as a class? Sometimes that solves strange css inherit or override problems (for me).
here is sample link: http://bootply.com/76369
this is html i use.
<div class="row">
<div class="col-md-6">.col-md-6</div>
<div class="col-md-6">.col-md-6</div>
</div>
bootstrap 3 has no container-fluid and row-fluid.
i cannot wrap it with .container class because it will become fixed layout.
how to make it fluid (full page width) layout? (without horizontal scrollbar)
with these markup. when you view in the result the x-scroll bar is visible so you can scroll to left and right that it should not.
edited: 2015-12-09
Already got answer and Bootstrap already released the fix since 3.1.0
I also have it and while waiting on them to fix it, I added this shame css :
body { overflow-x: hidden;}
it's an horrible alternative, but it work. I'll be happy to remove it when they'll have fixed the issue.
An other alternative, as pointed out in the issue, is to override .row :
.row {
margin-left: 0px;
margin-right: 0px;
}
This was introduced in v3.1.0: http://getbootstrap.com/css/#grid-example-fluid
Commit #62736046 added ".container-fluid variation for full-width containers and layouts".
This is a known issue in BS 3 - https://github.com/twbs/bootstrap/issues/9862?source=cc
I have tested on Bootply using the latest build, so keep watching GitHub for the latest updates/fix.
In Bootstrap 3, .row is must be used inside a .container or .container-fluid to counteract the negative margins on the row. This will eliminate the horizontal scrollbar.
From the docs...
"Rows must be placed within a .container (fixed-width) or
.container-fluid (full-width) for proper alignment and padding."
Bootstrap 4
The container>row>col relationship work the same way as 3.x...
"Containers are the most basic layout element in Bootstrap and are
required when using our default grid system"
If I understand you correctly, Adding this after any media queries overrides the width restrictions on the default grids. Works for me on bootstrap 3 where I needed a 100% width layout
.container {
max-width: 100%;
/* This will remove the outer padding, and push content edge to edge */
padding-right: 0;
padding-left: 0;
}
Then you can put your row and grid elements inside the container.
Update from 2014, from Bootstrap docs:
Grids and full-width layouts Folks looking to create fully fluid
layouts (meaning your site stretches the entire width of the viewport)
must wrap their grid content in a containing element with padding: 0
15px; to offset the margin: 0 -15px; used on .rows.
Just my 2 cents here. Mostly this will work for you, as it did for me.
body > .row {
margin-left: 0px;
margin-right: 0px;
}
I ran in to the same problem (wanting a fluid layout) but wanted to keep the responsive options with rearranging columns and so on for smaller screens and ended up with a small change to in variables.less:
// Large screen / wide desktop (last row of file)
#container-lg-desktop: 100%; //((1140px + #grid-gutter-width));
This value is used once in grid.less and sets
#media (min-width: #screen-lg-desktop) {
.container {
max-width: #container-lg-desktop;
}
....
}
The result is that over 1200px the grid is fluid (without horizontal scrollbars). Below that the normal responsive rules apply. You can of course set this to other media queries as well just as easily.
If you do not want to edit and compile .less yourself you could override the maxwidth in your own style sheet similair to below:
#media (min-width: 1200px) { /* or min-width: wherever-you-want-your-fluid-breakpoint */
body .container {
max-width: 100%;
}
}
All this assumes you use the normal Bootstrap grid syntax, including container, like below:
<div class="container">
<div class="row" >
<div class="col-md-6">.col-md-6</div>
<div class="col-md-6">.col-md-6</div>
</div>
</div>
Hope this helps!
In the latest version of Twitter Bootstrap the layout is fluid by default, hence you don't need extra classes to declare your layout as fluid.
You can further refer to -
http://bassjobsen.weblogs.fm/migrate-your-templates-from-twitter-bootstrap-2-x-to-twitter-bootstrap-3/
http://blog.getbootstrap.com/
This worked for me. Tested in FF, Chrome, IE11, IE10
.row {
width:99.99%;
}
The horizontal scrollbar can appear if the container-fluid div is placed directly inside the body.
The correct way to use a container-fluid structure is:
<body>
<section>
<div class="container-fluid">
<div class="row">
<!-- content goes here -->
</div>
</div>
</section>
</body>
So, try wrapping your container-fluid DIVs inside an outer div, such as a <div id="wrap"> or a <section> or <article> or <aside> or other specialized <div>, and presto! no horizontal scrollbar.
In Bootstrap 3, putting columns immediately under body should give you a fluid layout without horizontal scroll bar
<body>
<div class="col-md-6">.col-md-6</div>
<div class="col-md-6">.col-md-6</div>
</body>
Bootstrap 3.0 version is tricky they will add fix for this issue and probably return container-fluid in Bootstrap 3.1. But until then here is a fix that I'm using:
First of, you would need custom container and set it to 100% width, and then you will need to fix row margin disposition, and navbar too if you have it:
/* Custom container */
.container-full {
margin: 0 auto;
width: 100%;
}
/*fix row -15px margin*/
.container-fluid {
padding: 0 15px;
}
/*fix navbar margin*/
.navbar{
margin: 0 -15px;
}
/*fix navbar-right margin*/
.navbar-nav.navbar-right:last-child {
margin-right: 0px;
}
You can stack container-full and container-fluid classes on root div, and you can use container-fluid later on.
Hope it helps, if you need more info let me know.
Found this workaround
.row {
margin-left: 0;
margin-right: 0;
}
[class^="col-"] > [class^="col-"]:first-child,
[class^="col-"] > [class*=" col-"]:first-child
[class*=" col-"] > [class^="col-"]:first-child,
[class*=" col-"]> [class*=" col-"]:first-child,
.row > [class^="col-"]:first-child,
.row > [class*=" col-"]:first-child{
padding-left: 0px;
}
[class^="col-"] > [class^="col-"]:last-child,
[class^="col-"] > [class*=" col-"]:last-child
[class*=" col-"] > [class^="col-"]:last-child,
[class*=" col-"]> [class*=" col-"]:last-child,
.row > [class^="col-"]:last-child,
.row > [class*=" col-"]:last-child{
padding-right: 0px;
}
This is what worked for me. I added a style inline to remove the small margin on the right. I don't really like to do inline styling, but this lone style attribute in my html makes it easy for me to remember about the hack-job spliced into my otherwise well separated code. It also eliminates the concern of my external styles loading before or after the bootstrap default stylesheet.
<div class="row" style="margin-right:0px;">
<div class="col-md-6">
<div class="col-md-6">
</div>
Apply to the body seems to get rid of the horizontal scrollbar
overflow-x: hidden;
If it still actual for someone, my solution was as follows:
.container{
overflow: hidden;
overflow-y: auto;
}
It's already fluid by default. If you want to be fluid for less width instead of col-md-6 use col-sm-6 or col-xs-6.
You can fix this problem without disturbing the bootstrap css and wait for a fix in the next version, so you can simply wrap your row by defining you own class .container-fluid with padding.
//Add this class to your global css file
<style>
.container-fluid {
padding: 0 15px;
}
</style>
//Wrap your rows in within this .container-fluid
<div class="container-fluid">
<div class="row">
<div class="col-md-3">content</div>
<div class="col-md-9">content</div>
<div class="col-md-3">content</div>
</div>
</div>
You can add a 10px padding on the sides to your body element if all it's children are rows
body {
padding: 0 10px;
}
if your HTML markup looks something like this:
<body>
<div class="row"></div>
<div class="row"></div>
<div class="row"></div>
</body>
The rows have a 10 px negative margin. That's what's causing the overflow. If you add 10px padding to the body, they will cancel each other out.
The only thing that assisted me was to set margin:0px on the topmost <div class="row"> in my html DOM.
This again wasn't the most appealing way to solve the issue, but as it is only in one place I put it inline.
As an fyi the container-fluid and apparent bootstrap fixes only introduced an increased whitespace on either side of the visible page... :( Although I came across my solution by reading through the back and forth on the github issue - so worthwhile reading.
Summarizing the most relevant comments in one answer:
this is a known bug
there are workarounds but you might not need them (read on)
it happens when elements are placed directly inside the body, rather than inside a container-fluid div or another containing div. Placing them directly in the body is exactly what most people do when testing stuff locally. Once you place your code in the complete page (so within a container-fluid or another container div) you will not face this problem (no need to change anything).
Please, consider the following jsFiddle - http://jsfiddle.net/mark69_fnd/hwCuB/ (you can find the code after the body of the question).
It represents a trivial example of the classic header, content, footer HTML layout. Notice that:
The content never overlaps with the footer. Resizing the window will finally create a vertical scrollbar rather than move the content over the footer.
There are no redundant scrollbars.
No absolute heights, except of the footer, which may be assumed to be no higher than 2em.
The content height is less than the available height between the header and the footer.
I would like to keep the first three properties, but change the last one, so that the content height is the full height between the header and the footer. And I would like to do so without resorting to javascript.
How can I do so, if at all?
EDIT
The given html and css are just an example. You are free to change them as long as the final result satisfies the conditions of my question.
EDIT2
Apparently, I am not very clear on what I want to achieve with the content. Here is what I have now:
Notice how the content does not extend the full height available to it between the header and the footer.
What I am after is this:
(edited in mspaint, I do not know to do it really)
EDIT3
Added an except clause to the 3rd condition:
except of the footer, which may be assumed to be no higher than 2em.
HTML:
<html>
<head>
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/3.7.3/build/cssreset/reset-min.css">
</head>
<body>
<div class="container">
<div class="header">
Header goes here.
</div>
<div class="content">
<div class="innerWrapper">
Content goes here.
</div>
</div>
<div class="footer">
<div class="status">
Footer goes here.
<div>
</div>
</div>
</body>
</html>
CSS:
html, body {
height: 100%;
width: 100%;
}
.container {
position: relative; /* needed for footer positioning*/
margin: 0 auto;
height: auto;
min-height: 100%;
background-color: #ddd;
}
.content {
padding: 0em 0em 2em; /* bottom padding for footer */
background-color: #bbb;
}
.footer {
position: absolute;
width: 100%;
bottom: 0; /* stick to bottom */
}
.status, .header {
background-color: #999;
border: solid 1px #000000;
}
There might be couple ways to do this, but the only ways i can think of at the moment all involve setting/knowing the height of your header and footer.
Here is one using display:table http://jsfiddle.net/fLnkf/
There may be other solutions depending on if your requirements allow you to change your html or use CSS3.
hope this helps!
At the moment I have this (standard) code which gives me a full-width background but constrains the header to centered 960px:
<div style="background-color: #222">
<header style="width: 960px; margin: 0 auto;">
<h1>Site Title</h1>
</header>
</div>
Is there a way I can apply those to a single element in CSS, and avoid the div altogether? I considered this jQuery hack to calculate and set left and right padding on header but a pure CSS solution would be better.
Desired HTML:
<header>
<h1>Site Title</h1>
</header>
It might not be possible but thought I'd ask before dismissing it!
You can ditch the div wrapper in favor of :before and :after. Here's an article on it: http://css-tricks.com/9443-full-browser-width-bars/
The end of the article has a link to information on which browsers support :before and :after. For those that don't, you could use a javascript polyfill.
if it's for the whole page you can set the background on the <body> otherwise I think you'll need to use a <div> like you have.
Would something as this simple work?
header {
background-color: #222;
display: block;
width: 100%;
}
header h1 {
background: #fcc;
color: #000;
margin: 0 auto;
width: 960px;
}
Edit this jsFiddle: http://jsfiddle.net/t6wBv/2/
I take it this is HTML5 you're working with? There's no need to wrap a div around a header. This is one of the beautiful things about HTML5!
What I would do is give this particular header an ID, and stylize from there. For instance:
Your CSS file (or included CSS):
#title {
background-color: #222;
margin: 0 auto;
width: 960px;
}
Your HTML:
<header id=#title>
<h1>Site Title</h1>
</header>
This link kind of does the same thing you're looking to do!
Actually it is possible using just a single element. Thanks to the fact that padding in percentage refers to parent's width.
In fiddle I used div but it should work with header as well.