I'm trying to create a four column layout where each column grows and shrinks with the size of the window, but each column has a minimum width and when the window is too small for all four columns to fit in a single row, it transitions to a single column with each section taking up the full width.
I've been unable to do this with either flex-box or CSS grid. And I'd like to do this without a media query. Using a media query would solve the issue pretty easily, but I don't like them!
.col {
width: 100%;
display: flex;
flex-wrap: wrap;
}
.section {
margin: 10px 0px 0px 10px;
min-width: 250px;
height: 400px;
background-color: gray;
flex: auto;
}
<div class="col">
<div class="section">
</div>
<div class="section">
</div>
<div class="section">
</div>
<div class="section">
</div>
</div>
And a codepen: https://codepen.io/WriterState/pen/oRKxMj
Media queries are great, but they are not always a viable substitute for container queries (which sadly do not exist).
A horizontal to vertical layout switch can be achieved using CSS calc when you know how many columns you will have.
.child{
min-width: 25%; /* 100% divide number columns */
max-width: 100%;
width: calc((50rem - 100%) * 1000); /* Replace 50rem with size of .parent when you want switch to happen */
}
The width is calculated as your desired breakpoint minus the width of the parent container. This either generates a negative number and the min-width is applied, or a large number in which case the max-width takes over.
If you are using flex-box then width can also be flex-basis.
Source: https://www.sitepoint.com/responsive-css-patterns-without-media-queries/
Related
I have the following html:
<div class="row">
<div class="item">
<img src="image1" />
</div>
<div class="item">
<video>
<source src="video1" />
</video>
</div>
</div>
I'd like it for row to automatically adjust its height and for the subchildren of row to automatically adjust their widths and heights such that the aspect ratios of the content under the img and video tags remains the same, that row will have a width of 100%, and that there is no empty space within row.
In other words, I'm trying to make a content-responsive grid row with flexbox. Like so:
Except that rows and columns automatically change size to preserve image aspect ratios without creating gaps.
My current CSS attempt is as follows:
.row {
width: 100%;
display: flex;
flex-direction: row;
flex-wrap: nowrap;
}
.item {
position: relative;
min-height: 100%;
}
.item video {
max-width: 100%;
max-height: 100%;
}
.item img {
max-width: 100%;
max-height: 100%;
}
There seems to be no effective way to do this with flexbox. The only example I could find of this working properly was on a wix website, which works by doing the following:
All items are positioned absolutely and have width and height set manually.
Initial width and height of all items are zero to prevent initial rendering problems.
A function is defined which manually calculates the correct position, width, and height of all items.
This function is called on every resize and immediately after page load.
I am trying to create a responsive grid with flexbox:
On large screens, there should be three columns in one row
On smaller screens, just two rows or one
My code so far:
.grid {
display: flex;
flex-wrap: wrap;
}
.gridColumn {
flex: 1 1 0px;
background-color: lightblue;
min-width: 200px;
}
<div class="grid">
<div class="gridColumn">
<p>first column</p>
</div>
<div class="gridColumn">
<p>second column</p>
</div>
<div class="gridColumn">
<p>third column</p>
</div>
</div>
Now, I would like to set margins only between the columns (not on the sides of the grid as well), which should also behave correctly when the screen is resized. Does anybody know of a way to achieve this?
You can add a margin to the grid items...
.gridColumn {
margin: $margin;
}
... which is then offset by its container.
.grid {
margin: -$margin;
}
To avoid overflow, you could apply overflow-x: hidden to the body.
Codepen example
It's crashed on this part of code
.gridColumn + .gridColumn {
margin-left: 20px;
}
You should to try use media query and set margin-left: 0; on small screens.
Above part of code is still working because flex-wrap only changing the position of the "third column", that column still have "sister" before and margin-left is working.
I have two different divs with various contents, and would like them to be the same height and width. It seems like a bad idea to set their height and width to a fixed pixel size, because their size should probably vary based on browser/screen size. Setting their width to a percentage works, but percentage is not an option for height.
Is there a way to ensure two divs have the same dimensions without setting to fixed pixel sizes? Or are fixed pixel sizes really so bad?
Having an outer div with display: table; and these two divs inside it with display: table-cell; should work for you.
I'd suggest defining a container div which varies according to screen width (using #media screen) and using css3's flex to define your divs like so :
HTML
<div class="container">
<div class="first-div">first div </div>
<div class="second-div">second div </div>
</div>
CSS
.first-div{
-webkit-flex: 1; /* Safari 6.1+ */
flex: 1;
background-color:yellow;
border: 2px solid black;
}
.second-div{
-webkit-flex: 1; /* Safari 6.1+ */
flex: 1;
background-color:blue;
border: 2px solid black;
}
.container{
width:auto;
display: -webkit-flex; /* Safari */
-webkit-align-items: center; /* Safari 7.0+ */
display: flex;
align-items: center;
}
https://jsfiddle.net/sujy3bq4/19/
Hope this helps you.
When using height, you need to make sure that you have a full body to work with. By default, the body height is auto. If you set the height to 100%, you can start to use the height attribute on child elements.
Just remember that height is always set to it's parent:
body,html{height:100%;}
div{width:50%; height:50%;}
.el1{float:left; background:#f00;}
.el2{float:right; background:#0f0;}
<div class="el1"></div>
<div class="el2"></div>
If using CSS3 is an option in your case then you can use the 'ViewPort Percentage Lengths" Details on W3.
Something like below should work. (Refer question here for more details.)
div {
height:100vh;
}
Super easy and intuitive way to make responsive, square containers
Scalable percentage heights with padding-bottom:
See Codepen
Basically, set the height to 0, and set the bottom padding to any percentage you'd like.
.box {
float: left;
width: 23%;
height: 0;
padding-bottom:23%;
margin: 1%;
background-color: #e6e6e6;
box-sizing: border-box;
text-align: center;
}
<section>
<div class="box">
1
</div>
<div class="box">
2
</div>
<div class="box">
3
</div>
<div class="box">
4
</div>
</section>
I guess I have the simplest problem ever and cannot find a ready solution.
I need to make a grid with fixed widths and fixed distance between them.
I need x columns a 400px (x = total width/400), and during browser resizing I would need this grid to shrink, column by column (columns must always keep their width size and distance between them).
The content flows over all columns and should spread out over all columns.
That's why I don't like any open source grid system (Boostrap, Skeleton, etc.) they all use %width, and columns always change width on resizing.
What would be the simplest way?
Edit/Clarification:
This is how it looks without columns: http://jsfiddle.net/xjrt8qrm/16/show/
<div>See the fiddle</div>
I want it to have x columns. x is the maximum possible amount of 400px columns, depending on the users resolution. I want only one row of columns, so the content spreads like on a newspaper from top to bottom.
So it will look somehow like this on a PC: http://i.imgur.com/kmd620p.png (You can ignore the text/comments there).
It's pretty simple. The container holds the contents together. Float left will cause them to line up left to right. When the container runs out of space to hold them, they'll drop from the right to a row below one at a time. The clear div clears out the float so that it doesn't propagate to other nearby classes. Obviously, you'll have to handle padding, margins, etc as your style dictates.
If you needed newspaper like vertical layout, you could try a solution like this one
You could use media queries in this manner or even overflow:none to hide columns that didn't fit if that was your desired behavior.
Here's a simple solution:
HTML:
<div class="container">
<div class="fourhundred">
Div 1
</div>
<div class="fourhundred">
Div 2
</div>
<div class="fourhundred">
Div 3
</div>
<div class="clear"></div>
</div>
CSS:
.fourhundred {
width: 400px;
margin: 10px;
float: left;
}
.clear { clear:left }
.container { width: 100% }
This is why flexbox have been designed. Add to your container:
.container {
display: flex;
justify-content: space-between;
align-content: space-between;
width:100%;
}
as in this Fiddle
Simply used width: calc(100% / 3); you can use any value instead of 3. Divided the whole width into 3.
here is the Fiddle Demo
<div id = "main">
<div id ="sub">One
</div>
<div id ="sub">Two
</div>
<div id ="sub">Three
</div>
</div>
CSS Part
#main{
border: 2px solid black;
height:100px;
width:100%;
position: relative;
display:flex;
}
#sub{
border:1px solid red;
width: calc(100% / 3);
height: calc(100% - 40px);
padding:10px;
margin : 5px;
display:inline-block;
}
I want a container with two columns. Details:
The container
Width should adjust to 100% of its parent element (easily accomplished).
Height must adjust to contain both columns (i.e. its height should be exactly equal to the larger height of the two columns, so there is no overflow and scrollbars never show)
Should have a minimum size equal to double the width of the left column.
The columns in general
Should be of variable height, adjusting to the height of their content.
Should be side-by-side, such that their top edges are in line.
Should not break the layout or wrap under each other if even a single pixel of border, padding, or margin is applied to either one, because that would be extremely unstable and unfortunate.
The left column specifically
Must have a fixed, absolute width in pixel units.
The right column specifically
Width must fill the remaining space in the container. In other words...
Width must equal the container width minus the width of the left column, such that if I place a DIV block element inside this column, set its width to 100%, give it a height of something like 10px, and give it a background color, I will see a 10px high colored strip that goes from the right edge of the left column to the right edge of the container (i.e. it fills the right column's width).
Required stability
The container should be able to resize (by resizing the browser window) down to its minimum width (specified earlier) or to a much larger width without breaking the layout. "Breaking" would include the left column changing size at all (remember it's supposed to have a fixed pixel width), the right column wrapping under the left one, scrollbars appearing, block elements in the right column failing to take up the entire column width, and in general any of the aforementioned specifications failing to remain true.
Background
If floating elements are used, there should be no chance that the right column will wrap under the left one, that the container will fail to contain both columns (by clipping any part of the column or allowing any part of the columns to overflow its boundary), or that scrollbars will appear (so I'd be weary of suggesting the use of anything other than overflow:hidden to trigger floating-element containment). Applying borders to the columns should not break the layout. The content of the columns, especially of the right column, should not break the layout.
There seems to be a simple table-based solution to this, but under every circumstance it fails miserably. For example, in Safari, my fixed-width left column will shrink if the container gets too small, rather than maintaining the width I specified. It also seems to be the case that CSS width, when applied to a TD element refers to a minimum width, such that if something larger is placed inside it, it will expand. I've tried using table-layout:fixed; doesn't help. I've also seen the case where the TD element representing the right column will not expand to fill the remaining area, or it will appear to (for example a third column 1px wide will be pushed all the way to the right side), but putting a border around the right column will show that it's only as wide as its inline content, and block-level elements with their width set to 100% do not fill the width of the column, but rather match the width of the inline-content (i.e. the width of the TD seems to be completely dependent on the content).
One potential solution I have seen is too complex; the solution needs to work in IE8, Firefox 4, and Safari 5.
Here you go:
<html>
<head>
<title>Cols</title>
<style>
#left {
width: 200px;
float: left;
}
#right {
margin-left: 200px;
/* Change this to whatever the width of your left column is*/
}
.clear {
clear: both;
}
</style>
</head>
<body>
<div id="container">
<div id="left">
Hello
</div>
<div id="right">
<div style="background-color: red; height: 10px;">Hello</div>
</div>
<div class="clear"></div>
</div>
</body>
</html>
See it in action here: http://jsfiddle.net/FVLMX/
Try this: Live Demo
display: table is surprisingly good. Once you don't care about IE7, you're free to use it. It doesn't really have any of the usual downsides of <table>.
CSS:
#container {
background: #ccc;
display: table
}
#left, #right {
display: table-cell
}
#left {
width: 150px;
background: #f0f;
border: 5px dotted blue;
}
#right {
background: #aaa;
border: 3px solid #000
}
Piece of cake.
Use 960Grids Go to the automatic layout builder and make a two column, fluid design. Build a left column to the width of grids that works....this is the only challenge using grids and it's very easy once you read a tutorial. In a nutshell, each column in a grid is a certain width, and you set the amount of columns you want to use. To get a column that's exactly a certain width, you have to adjust your math so that your column width is exact. Not too tough.
No chance of wrapping because others have already fought that battle for you. Compatibility back as far as you likely will ever need to go. Quick and easy....Now, download, customize and deploy.
Voila. Grids FTW.
Over 11 years later. Apply display:grid to the container and divide the available space by grid-template-columns: 100px 1fr. Where 1fr represents a fraction of 100% of the remaining space.
<html>
<head>
<title>Cols</title>
<style>
#container {
display: grid;
grid-template-columns: 100px 1fr;
}
</style>
</head>
<body>
<div id="container">
<div id="left">
Hello
</div>
<div id="right">
<div style="background-color: red; height: 10px;">Hello</div>
</div>
</div>
</body>
</html>
As suggested by mtmurdock it is possible to remove the .clear rule and move it to the pseudo-element #container::after.
<html>
<head>
<title>Cols</title>
<style>
#left {
width: 200px;
float: left;
}
#right {
margin-left: 200px;
/* Change this to whatever the width of your left column is*/
}
#container::after {
clear : left;
display: block;
content: '';
}
</style>
</head>
<body>
<div id="container">
<div id="left">
Hello
</div>
<div id="right">
<div style="background-color: red; height: 10px;">Hello</div>
</div>
</div>
</body>
</html>
Another idea is to include the left div in the right div,
which in turn coincides with the line container:
[right][left] ... [/left] ..... [/right]
x { border: thick solid navy; padding: 2px; }
.lineContainer, .container > p {
padding-left: 100px;
margin: 0;
line-height: 1.5;
}
.left, em {
margin-left: -100px;
display:inline-block; box-sizing: border-box; width: 100px;
vertical-align: top;
}
.div-in-div {
display:inline-block; box-sizing: border-box; width: 100%;
vertical-align: top;
}
<h3>Layout: div-left is contained within the right-div / lineContainer</h3>
<pre>
[right][left] … [/left] … [/right]
</pre>
<div class="lineContainer" style="background:floralwhite; "><div class="left">Hello</div>Hello there</div>
<p>Using the above scheme,
we can make old-fashioned typewriter tab stops as shown here.</p>
<h3>The Capital Cities of the UK</h3>
<div class="container" style="background-color: floralwhite; ">
<p><em>England</em> - The capital is London.</p>
<p><em>Scotland</em> - The capital is Edinburgh.</p>
<p><em>Wales</em> - The capital is Cardiff.</p>
<p><em>Northern Ireland</em> - The capital is Belfast.</p>
<p><em>The capital of the UK is</em> - London.</p>
<p><em>Source</em>- Project Britain, capitals.</p>
</div>
<h3>Div in div</h3>
<div class="lineContainer" style="background:floralwhite; ">
<div class="left">Div in container</div><!--No white space here
--><p class="div-in-div" style="background: red; font-size: x-large; margin: auto 0; ">Hello there</p>
</div>