I have problems to place N divs side by side with full browser width
I want like this. when you resize browser space between divs must stay same and divs must resize in width.
|div| |div| |div|
| div | | div | | div |
One solution would be to use percentages:
div.mydiv {
width: 33%;
display: inline-block;
}
If you do this, be careful with padding: that adds to a div's width, possibly causing overflow. This can be fixed if you support only IE >=8, by doing
div.mydiv {
width: 33%;
display: inline-block;
-moz-box-sizing: border-box; /* OMG why doesn't Firefox support this yet */
-webkit-box-sizing: border-box; /* Safari below 5.1, including 5 */
box-sizing: border-box;
}
And if you do that, there's even one more possible problem: space between the divs. This occurs because you have empty text nodes in between them, and display: inline-block thinks that's OK: elements laid out in an inline-type fashion can be interspersed with blank text nodes. To fix this, there's a pretty bad hack:
div.containerOfAllTheDivs {
font-size: 0;
}
div.mydiv {
font-size: 12px; /* or whatever */
/* plus the above stuff */
}
This makes it so that any text (e.g. whitespace) that appears inside the container is zero-sized, unless it appears inside the divs you are stacking next to each other, in which case it reverts back to 12px. As I said, a pretty bad hack. But it works.
The more general solution is the new flexbox proposal, but that is still under heavy revision: there are two outdated versions implemented in various browsers, with the latest one not being implemented in any as of today (2012-05-15). If you know your exact environment, though, this might be a good solution.
For two divs, just do (Demo):
div
{
width: 49%;
float: left;
}
For three, do (Demo):
div
{
width: 33%;
float: left;
}
If you need an arbitrary number of divs, you have two options:
If the number is determined by the server (value is coming from a database or a session or whatever), you can generate appropriate CSS on the server side. This solution is preferable.
If not, you need JavaScript to calculate the viewport's width, and assign width values accordingly to your divs.
The same thing could be achieved using CSS3 Flexible Box Style Layout with very less coding. Well it depends upon the browser you are planning to support.
Now Flexible box layout is supported only in webkit engines & mozilla
Putting this as an answer because I guess it's valid and may serve you well. 960.gs and bootstrap both provide scaffolding for layouts identical to what you want. 960.gs is just layout but if bootstrap suits you, you can customize it on their site to just get the bits that deal with layout. One caveat for bootstrap, I haven't found a way to remove the left margin on the div columns. 960.gs includes alpha and omega classes that set margin-left and margin-right to 0 respectivley. I had to add these to bootstrap when I used it.
Using one of those scaffoldings will save you a lot of time and effort. If you have to hand your code off to somebody else later or even just have somebody else working on it with you, using a scaffolding will help them work with your code too.
Related
I would like to use media queries to resize elements based on the size of a div element they are in. I cannot use the screen size as the div is just used like a widget within the webpage, and its size can vary.
Yes, CSS Container Queries are what you're looking for. The CSS Containment Module is the specification that details this feature.
You can read more about the decade of work, including proposals, proofs-of-concept, discussions and other contributions by the broader web developer community here! For more details on how such a feature might work and be used, check out Miriam Suzanne's extensive explainer.
Currently only Chromium 105+ supports Container queries out of the box, though Safari 16 will include support as well. Hopefully it won't be much longer before we see a robust cross-browser implementation of such a system. It's been a grueling wait, but I'm glad that it's no longer something we simply have to accept as an insurmountable limitation of CSS due to cyclic dependencies or infinite loops or what have you (these are still a potential issue in some aspects of the proposed design, but I have faith that the CSSWG will find a way).
Media queries aren't designed to work based on elements in a page. They are designed to work based on devices or media types (hence why they are called media queries). width, height, and other dimension-based media features all refer to the dimensions of either the viewport or the device's screen in screen-based media. They cannot be used to refer to a certain element on a page.
If you need to apply styles depending on the size of a certain div element on your page, you'll have to use JavaScript to observe changes in the size of that div element instead of media queries.
Alternatively, with more modern layout techniques introduced since the original publication of this answer such as flexbox and standards such as custom properties, you may not need media or element queries after all. Djave provides an example.
I've just created a javascript shim to achieve this goal. Take a look if you want, it's a proof-of-concept, but take care: it's a early version and still needs some work.
https://github.com/marcj/css-element-queries
From a layout perspective, it is possible using modern techniques.
Its made up (I believe) by Heydon Pickering. He details the process here: http://www.heydonworks.com/article/the-flexbox-holy-albatross
Chris Coyier picks it up and works through a demo of it here: https://css-tricks.com/putting-the-flexbox-albatross-to-real-use/
To restate the issue, below we see 3 of the same component, each made up of three orange divs labelled a, b and c.
The second two's blocks display vertically, because they are limited on horizontal room, while the top components 3 blocks are laid out horizontally.
It uses the flex-basis CSS property and CSS Variables to create this effect.
.panel{
display: flex;
flex-wrap: wrap;
border: 1px solid #f00;
$breakpoint: 600px;
--multiplier: calc( #{$breakpoint} - 100%);
.element{
min-width: 33%;
max-width: 100%;
flex-grow: 1;
flex-basis: calc( var(--multiplier) * 999 );
}
}
Demo
Heydon's article is 1000 words explaining it in detail, and I'd highly recommend reading it.
Update 2021/22
As mentioned in other answers, container queries are coming. There is a full spec for it, and its usage is detailed on MDN:
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries
and there is a polyfill to get browsers that don't yet support it up to speed:
https://github.com/GoogleChromeLabs/container-query-polyfill
There is a nice little overview video of it here:
https://www.youtube.com/watch?v=gCNMyYr7F6w
This has now shipped to Chrome (05 September 2022)
https://caniuse.com/css-container-queries
A Media Query inside of an iframe can function as an element query. I've successfully implement this. The idea came from a recent post about Responsive Ads by Zurb. No Javascript!
This is currently not possible with CSS alone as #BoltClock wrote in the accepted answer, but you can work around that by using JavaScript.
I created a container query (aka element query) polyfill to solve this kind of issue. It works a bit different than other scripts, so you don’t have to edit the HTML code of your elements. All you have to do is include the script and use it in your CSS like so:
.element:container(width > 99px) {
/* If its container is at least 100px wide */
}
https://github.com/ausi/cq-prolyfill
I ran into the same problem a couple of years ago and funded the development of a plugin to help me in my work. I've released the plugin as open-source so others can benefit from it as well, and you can grab it on Github: https://github.com/eqcss/eqcss
There are a few ways we could apply different responsive styles based on what we can know about an element on the page. Here are a few element queries that the EQCSS plugin will let you write in CSS:
#element 'div' and (condition) {
$this {
/* Do something to the 'div' that meets the condition */
}
.other {
/* Also apply this CSS to .other when 'div' meets this condition */
}
}
So what conditions are supported for responsive styles with EQCSS?
Weight Queries
min-width in px
min-width in %
max-width in px
max-width in %
Height Queries
min-height in px
min-height in %
max-height in px
max-height in %
Count Queries
min-characters
max-characters
min-lines
max-lines
min-children
max-children
Special Selectors
Inside EQCSS element queries you can also use three special selectors that allow you to more specifically apply your styles:
$this (the element(s) matching the query)
$parent (the parent element(s) of the element(s) matching the query)
$root (the root element of the document, <html>)
Element queries allow you to compose your layout out of individually responsive design modules, each with a bit of 'self-awareness' of how they are being displayed on the page.
With EQCSS you can design one widget to look good from 150px wide all the way up to 1000px wide, then you can confidently drop that widget into any sidebar in any page using any template (on any site) and
The question is very vague. As BoltClock says, media queries only know the dimensions of the device. However, you can use media queries in combination with descender selectors to perform adjustments.
.wide_container { width: 50em }
.narrow_container { width: 20em }
.my_element { border: 1px solid }
#media (max-width: 30em) {
.wide_container .my_element {
color: blue;
}
.narrow_container .my_element {
color: red;
}
}
#media (max-width: 50em) {
.wide_container .my_element {
color: orange;
}
.narrow_container .my_element {
color: green;
}
}
The only other solution requires JS.
The only way I can think that you can accomplish what you want purely with css, is to use a fluid container for your widget. If your container's width is a percentage of the screen then you can use media queries to style depending on your container's width, as you will now know for each screen's dimensions what is your container's dimensions. For example, let's say you decide to make your container's 50% of the screen width. Then for a screen width of 1200px you know that your container is 600px
.myContainer {
width: 50%;
}
/* you know know that your container is 600px
* so you style accordingly
*/
#media (max-width: 1200px) {
/* your css for 600px container */
}
You can use the ResizeObserver API. It's still in it's early days so it's not supported by all browsers yet (but there's several polyfills that can help you with that).
This API allows you to attach an event listener when resizing a DOM element.
Demo 1 - Demo 2
I was also thinking of media queries, but then I found this:
http://www.mademyday.de/css-height-equals-width-with-pure-css.html
Maintain the aspect ratio of a div with CSS
Just create a wrapper <div> with a percentage value for padding-bottom, like this:
div {
width: 100%;
padding-bottom: 75%;
background:gold; /** <-- For the demo **/
}
<div></div>
It will result in a <div> with height equal to 75% of the width of its container (a 4:3 aspect ratio).
This technique can also be coupled with media queries and a bit of ad hoc knowledge about page layout for even more finer-grained control.
It's enough for my needs. Which might be enough for your needs too.
For mine I did it by setting the div's max width, hence for small widget won't get affected and the large widget is resized due to the max-width style.
// assuming your widget class is "widget"
.widget {
max-width: 100%;
height: auto;
}
This question already has answers here:
Prevent scroll-bar from adding-up to the Width of page on Chrome
(20 answers)
Prevent a centered layout from shifting its position when scrollbar appears
(7 answers)
Closed 5 years ago.
Many programmers have asked how to stop their web page content — especially their centered web page content (margin: 0 auto;) — from shifting (being pushed) horizontally when the vertical scroll bar appears. This has been an ongoing problem for Ajax users and people like me who use hidden divs and tabs to organize data.
The problem occurs when the currently displayed page changes such that the height of the displayed material (the inner window height) is suddenly greater than the physical window height.
The problem is exacerbated by the reality that all scrollbars are not created equal. Different browsers give their scroll bars different widths, and that difference cannot (or, at least, should not) be predicted. In short, the ideal solution is scrollbar width independent.
This, therefore, is a self-answered question that rolls all those answers with commentary on their usefullness (where possible) along with my own solution into a single answer as of August 5, 2017. I've marked as duplicates as many of the previous questions as I can find so that people can find a comprehensive discussion of the issue.
Please note that this answer addresses problems with BODY contents shifting. If you have a DIV with a fixed height that has shifting problems, you should set the DIV width to a fixed (px) width so its scrollbar floats above the text and add some right-hand padding to keep the text from falling beneath it. Contributors: Hashbrown,
Avrahamcool,
Edward Newsome
Before going into individual solutions, it should be mentioned that they break down into three categories: CSS-, CSS3-, and Javascript-based solutions.
The CSS solutions tend to be rigid but very predictable and very well supported.
The CSS3 solutions have a CPU calculation cost like Javascript, but are easy to implement. In years previous to 2017, however, they had sporadic support in browsers. That is improving over time. Ultimately, they will likely be the best solution, but my own investigations today have demonstrated the support simply isn't consistent enough yet and, besides, legacy browser support is non-existent.
The Javascript solutions (whether in straight Javascript or in jQuery) need extra coding to make them robust as they have no intrinsic support for (e.g.) window resizing. However, they're the most predictable and the most backward compatible while still preserving the aesthetics of the page. I consider the line for legacy browsers to be between IE6 and IE7. Frankly, my condolences to anyone still using a browser that old.
Please note that I have not included every CSS3 and Javascript solution previously posted to Stack Exchange. Some, though novel, had substantial weaknesses and so were not included here.
**Solution #1: The CSS Solution**
Contributors: Hive7, koningdavid, Christofer Eliasson, Alec Gorge, Scott Bartell, Shawn Taylor, mVChr, fsn, Damb, Sparky, Ruben, Michael Krelin - hacker, Melvin Guerrero
Force the srollbar to always be on.
<style>
html {
overflow-y: scroll;
}
</style>
This solution is basically guaranteed to always work (there are some exceptions, but they're very rare), but it is aesthetically unpleasing. The scrollbar will always be seen, whether it's needed or not. While concensus is to use this solution in the html tag, some people suggest using it in the body tag.
Consequences
Microsoft (IE10+) has implented floating scroll bars which means your page may not be centered in it like it would be in other browsers. However, this seems to be a very minor issue.
When using structured interfaces like FancyBox, Flex-Box, or Twitter Bootstrap Modal this can cause a double-scrollbar to appear as those interfaces create their own scrollbars.
Programmers should avoid using overflow: scroll as this will cause both the vertical and horizontal scrollbars to appear.
Solution #1a: An Alternative
Contributors: koningdavid, Nikunj Madhogaria
A clever alternative, but one having only a minor aesthetic difference, is to do this:
<style>
html {
height: 101%;
}
</style>
This activates the scroll bar background but doesn't activate the scroll bar tab unless your vertical content actually overflows the bottom edge of the window. Nevertheless, it has the same weakness in that the scrollbar space is permanently consumed whether needed or not.
Solution #1b: A More Modern Solution
Contributors: Kyle Dumovic, SimonDos
Browsers are beginning to pick up the use of the overlay value for scrollbars, mimicking the floating scrollbar of IE10+.
<style>
html {
overflow-y: overlay;
}
</style>
This solution mimics the floating scrollbar in IE10+, but it is not yet available in all browsers and still has some implementation quirks. This solution is known not to work for infrastructure environments like Bootstrap Modal.
**Solution #2: The CSS3 Solution**
Use CSS3 to calculate widths. There are many ways to do this with advantages and disadvantages to each. Most disadvantages are due to (a) not knowing the actual scrollbar width, (b) dealing with screen resizing, and (c) the fact that CSS is slowly becoming yet-another-fully-functioning-programming language — like Javascript — but has not yet completely evolved into such. Whether or not it even makes sense for it to become such is a debate for another question.
The argument that users may disable Javascript and so a CSS-only solution is preferable is becoming irrelevant. Client-side programming has become so ubiquitous that only the most paranoid of people are still disabling Javascript. Personally, I no longer consider this a tenable argument.
It should be noted that some solutions modify margin and others modify padding. Those that modify margin have a common problem: if you have navigation bars, headers, borders, etc. that use a different color than the page background this solution will expose undesirable borders. It is likely that any solution using margin can be re-designed to use padding and vice-versa.
Solution #2a: The HTML-based Solution
Contributors: TranslucentCloud, Mihail Malostanidis
<style>
html {
margin-left: calc(100vw - 100%);
margin-right: 0;
}
</script>
Solution #2b: The BODY-based Solution
Contributors: Greg St.Onge, Moesio, Jonathan SI
<style>
body {
padding-left: 17px;
width: calc(100vw - 17px);
}
#media screen and (min-width: 1058px) {
body {
padding-left: 17px;
width: calc(100vw - 17px);
}
}
</style>
100vw is 100% of the viewport width.
Consequences
Some users have suggested this solution creates undesirable screen noise when the window is resized (perhaps the calculation process is occuring multiple times during the resize process). A possible workaround is to avoid using margin: 0 auto; to center your content and instead use the following (the 1000px and 500px shown in the example represent your content maximum width and half that amount, respectively):
<style>
body {
margin-left: calc(50vw - 500px);
}
#media screen and (max-width: 1000px) {
body {
margin-left: 0;
}
}
</style>
This is a fixed-scrollbar-width solution, which isn't browser independent. To make it browser independent, you must include Javascript to determine the width of the scrollbars. An example that calculates the width but does not re-incorporate the value is:
Please note that the code snippet below has been posted multiple times on Stack Exchange and other locations on the Internet verbatim with no firm attribution.
function scrollbarWidth() {
var div = $('<div style="width:50px;height:50px;overflow:hidden;position:absolute;top:-200px;left:-200px;"><div style="height:100px;"></div>');
// Append our div, do our calculation and then remove it
$('body').append(div);
var w1 = $('div', div).innerWidth();
div.css('overflow-y', 'scroll');
var w2 = $('div', div).innerWidth();
$(div).remove();
return (w1 - w2);
}
Solution #2c: The DIV-based Solution
Contributors: Rapti
Use CSS3 calculations applied directly to a container DIV element.
<body>
<div style="padding-left: calc(100vw - 100%);">
My Content
</div>
</body>
Consequences
Like all CSS3 solutions, this is not supported by all browsers. Even those browsers that support viewport calculations do not (as of the date of this writing) support its use arbitrarily.
Solution #2d: Bootstrap Modal
Contributors: Mihail Malostanidis, kashesandr
Users of Twitter Bootstrap Modal have found it useful to apply the following CSS3 to their HTML element.
<style>
html {
width: 100%;
width: 100vw;
}
</style>
Another suggestion is to create a wrapper around your content wrapper that is used to auto-detect changes in the viewport width.
<style>
body {
overflow-x: hidden;
}
#wrap-wrap {
width: 100vw;
}
#content-wrap {
margin: 0 auto;
width: 800px;
}
</style>
I have not tried either of these as I do not use Bootstrap.
**Solution #3: The Javascript Solution**
Contributors: Sam, JBH
This is my favorite solution as it deals with all the issues and is reasonably backward compatible to legacy browsers. Best of all, it's scrollbar-width independent.
<script>
function updateWindow(){
document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth);
document.body.onclick=function(){
document.body.style.paddingLeft = (window.innerWidth - document.body.clientWidth);
}
}
window.onload=updateWindow();
window.addEventListener("resize", updateWindow());
updateWindow();
</script>
Consequences
The final command to updateWindow(); should occur just before the </body> tag to avoid problems with dynamically-loaded content such as Facebook Like-Boxes. It would seem that it's redundant to the window.onload event, but not every browser treats onload the same way. Some wait for asynchronous events. Others don't.
The function is executed each and every time a user clicks within the web page. Gratefully, modern computers are fast enough that this isn't much of an issue. Still….
Finally, the function should be executed after any div is asynchronously updated (AJAX). That is not shown in this example, but would be part of the ready-state condition. For example:
xmlhttp.onreadystatechange=function(){
if(xmlhttp.readyState==4 && xmlhttp.status==200){
if(xmlhttp.responseText == 'false'){
//Error processing here
} else {
//Success processing here
updateWindow();
}
}
}
Solution #3a: Measuring Scrollbar Widths
Contributors: Lwyrn
This is a less valuable solution that takes the time to measure scrollbar widths.
<script>
var checkScrollBars = function(){
var b = $('body');
var normalw = 0;
var scrollw = 0;
if(b.prop('scrollHeight')>b.height()){
normalw = window.innerWidth;
scrollw = normalw - b.width();
$('#container').css({marginRight:'-'+scrollw+'px'});
}
}
</script>
<style>
body {
overflow-x: hidden;
}
</style>
Consequences
Like other solutions, this one permanently disables the horizontal scrollbar.
My website has a few sort of "display containers", into which content is loaded using .load(), depending on which item is selected. These display containers can be a few different states, depending on wether your viewing on a mobile device etc, such as all the containers having word spacing to give the images in them a bit of breathing room, or setting the content to justify.
Now, if I include the images in these containers from the start—that is to say, they are part of the initial DOM—everything shows up fine. The images will be spaced apart using word-spacing if that's the state the containers are told to be in, or the content will be justified if you're on mobile.
The problem is, once content is added to these containers, whether it be using .load() to take it from a different document where it is being stored, or .append(), it is not taking on these properties.
I've made a fiddle to demonstrate here. Unfortunately, I can't demonstrate the .load() function due to only being able to use it on pages from the same domain (at least that's what the jQuery documentation tells me), but you can still see exactly what I'm talking about from the .append() side of things.
In short;
Images in DOM initially work
Images appended / loaded into DOM do not
When mixing (some elements initial, some elements appended), this still holds true for the images placed in each of their separate ways.
If you examine the source of the mixture of initial/loaded, all elements look the same. The first 2 imgs here are the ones with proper word-spacing, while the rest do not have it.
If you add some spaces between the images when appending them it will treat the images like "words" and apply the spacing.
The word-spacing property increases or decreases the white space between words. It's not good for the image. Below should be fine for you:
.projectPagePieces {
width: 100%;
text-align: right;
border: 1px dotted blue;
line-height: 0;
}
.projectPagePieces img {
vertical-align: top;
display: inline-block;
margin-left: 25px;
}
I'm trying to create a fluid CSS grid, it works in Firefox and IE8+ but NOT in Safari/Chrome/Opera where the sub-pixel rounding issue becomes visible:
http://jsfiddle.net/bJKQ6/2/
.column {
float: left;
width: 25%;
}
The main container has a width of 100%, and if you change the browser size in Safari/Chrome/Opera you can see how the rounded widths are inconsistent.
After extensive reads about the problem I understood that "there is no right or wrong solution" for the sub-pixel rounding, but the Firefox way seems the best compromise to me.
(For example, if I set 4 divs at a width of 25% I expect the covered area to be 100%.)
I would like to know if there is a CSS only solution that I missed, or alternatively some JavaScript to solve the problem.
Thanks!
UPDATE: As of May 2014, Chrome 33 and Safari 7 seem to have picked up the "Firefox way".
Stubbornella's OOCSS framework (links below) grids module deals with this by giving the last column the following overrides:
float: none;
overflow: hidden;
width: auto;
This allows it to occupy whatever width remains within the container.
A bit of browser-forking (IE, ptzsch…) is necessary to get the same behaviour:
https://github.com/stubbornella/oocss/blob/master/core/grid/grids.css
https://github.com/stubbornella/oocss/wiki/grids
It sucks there isn't a nice option for this that will round pixels up and down for each browser, but in lieu of that, I usually do:
.nested:last-child {
float: right;
}
.nested:first-child {
float: left;
}
This will float the last child to the right so the px unalignment isn't obvious, but if it's the only element (say a div that is 33% width), then it will continue to float left.
I am making a horizontal content slider, and need to put an arbitrary number of equally-sized elements in a row inside the slider div, so i can shift the slider div back and forth and display one element at a time on the page. These elements could be anything: divs, imgs, whatever.
Currently I am floating all the elements, and in order to prevent them from dropping onto the next row, using javascript to sum up the widths of all the elements on page load and manually fix the width of the slider in order to fit all of them.
Naturally I do not want to do this. I have looked at the CSS Flexible Box Model and it seems it would do what i need, but it does not appear very often outside of the W3C specification and i'm not sure how well supported it is. Does anyone have any experience using it? Apart from that, is there any other non-javascript way of lining up a bunch of divs side by side and having the parent expand laterally to fit?
Flexbox isn't really standardised or widely-supported enough to use yet. It's supported in newer browsers including IE10, but it's likely to be a long time before that's your baseline.
There are some ways to work around it. For example you can use white-space: nowrap to make inline children not fall down to the next line, in combination with float: left to make the parent shrink-wrap its width around the children. Then if you want the children to be stackable blocks you could use tables or inline blocks:
#slider { white-space: nowrap; float: left; border: dotted blue 1px;}
#slider .box { display: inline-block; width: 100px; border: dotted red 1px; }
<div id="slider">
<span class="box">foo</span
><span class="box">bar</span
><span class="box">bof</span
><span class="box">zot</span
>...
</div>
(Using <span> is needed for inline-block in IE7, and the odd > placement is to prevent unwanted whitespace between the boxes.)
As you may have seen, every browser may render things differently, but if you apply the style display:inline; to the elements in the slider, and width:auto; to the container element, they should not wrap.