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;
}
Related
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/
I didnt find an answer to this, so:
I am trying to do this in my blog:
- 2 rows (using div tag, not table)
- In each row, there will be a square image of certain size in percentage of width (e.g. 40%, I dont know how to set height to keep square form) and a color square with text inside, from the same size as the image.
square image text inside square
text inside square square image
I have this so far:
<style type="text/css">
.element {
float:left;
width: 50vh;
height:50vh;
border: 1px solid #000000;
margin:0 10px 0 0;
margin-left:5%;
margin-right:5%;
margin-top:10%;
align:center;
}
</style>
<div class="element">
<img src="wp-content/uploads/2015/04/luices.jpg" alt="Mountain View" width="400px">
</div>
<div class="element">Some text</div>
<div class="element">Some text</div>
<div class="element">
<img src="wp-content/uploads/2015/04/luices.jpg" alt="Mountain View" width="400px">
</div>
But have many problems:
1- I dont know how to use "vh" in width, and also, as far as I know, Browser compatibility is a problem with it. I just want to place these two squares 40% of width each one, separated by 7% of width (from sides and from each other).The same for the second row.
2- I need mobile compatibility also.
3- When you open the website in a small window (or phone), the second square will go down (thats ok) but I need that the order of squares to be:
square image
text inside square
square image
text inside square
Which is different from what every browser does with my code, wich is keeping the same original order: image,text,text,image.
I hope I explained well.
Thank you very much.
Bob
So in order to get the correct layout on a mobile device, you need to use the #media attribute, to set the css properties to be mobile friendly.
I made a plnkr that I tested on both my desktop and nexus 5, the key though are these two css properties:
div.row{
min-height: 25vh;
margin-bottom: 4vw;
}
div.col-40{
background-color: #333;
width: 44vw;
min-height: 25vh; /* set to the same as div.row min-height */
max-height: 25vh; /* set to the same as div.row min-height */
margin-left: 1vw;
padding: 1vh;
overflow: hidden;
text-align: center;
display: inline-block;
}
http://plnkr.co/edit/d2C3xOiNYjaUqVeX2yf4?p=preview
Basically you need to wrap the div's that you want next to each other, in another div, in this case .row.
If you have images that are larger than the div, the overflow will be hidden. You will more than likely need to mess with the css for your blog, but hopefully this gets you where you need to be.
You also should probably be using vw for the width properties (vw = viewport width). 1 vw or 1 vh = 1/100th of the viewport width or height.
The float:left; more than likely is messing up the div order. I prefer to use a display:inline-block; with a relational width value, as done with vw.
I would consider myself to be an intermediate/advanced CSS/HTML coder but I'm stumped on how to do the following scenario.. I'm starting to think it is impossible but I really want to believe it is..
Let's say the wrapper width is 1000px.
Within it is three columns. The two outside columns are the same width, this width is decided by the center column. The center column is the only one with content, just one line of text with 30px of padding on either side. So if the line of content is 100px with padding, than the other two columns would be (1000-100)/2 each..
Is there a dynamic way to have the two outside columns adjust to the varying width of the center column that is defined by its varying contents, one line of text?
Graphic of what I am trying to accomplish:
The very closest I could come up with was to use display: table; and table-cell. This creates the dynamic effect you're looking for, but I don't think you can get your desired effect without setting an explicit width to the center element.
HTML:
<div id="wrap">
<div id="left">
Left
</div>
<div id="center">
center
</div>
<div id="right">
Right
</div>
</div>
CSS:
#wrap
{
width: 1000px;
display: table;
}
#wrap div
{
display: table-cell;
border: 1px solid #000;
width: auto;
}
#center
{
padding: 0 30px;
text-align: center;
}
You can check out my attempt here, it has some buttons for you to see the different states, width on/off and add text etc. (the jQuery has nothing to do with the solution)
I think this is as close as you're going to get with pure CSS.
Good 'ole tables to the rescue:
http://jsfiddle.net/hgwdT/
Actually I think tables are the devil, but this works as you described. And so here it is using display: table-cell on the child divs, so it is functionally the same using nicer markup:
http://jsfiddle.net/XXXdB/
The center element can indeed have a dynamic width; to prevent the content from being squished, I simply added a white-space: nowrap to the p containing the text.
I also confirmed that this solution works in IE8 and FF, in addition to Chrome.
This not the most elegant solution, but it works. I wanted to go the pure CSS route, but couldn't figure it out. Nice work, jblasco and Kyle Sevenoaks, on figuring that out!
Here is my jsFiddle demo. If you don't mind using a little JavaScript though (utilizing jQuery in my example):
HTML:
<div id="wrapper">
<div class="side"></div>
<div id="middle">One line of text.</div>
<div class="side"></div>
</div>
CSS:
#wrapper {
margin: 0 auto;
width: 1000px;
}
#wrapper div {
float: left;
height: 300px;
}
.side {
background: #ddd;
}
#middle {
background: #eee;
padding: 0 30px;
text-align: center;
}
JavaScript:
var adjustSize = function(){
// Declare vars
var wrapper = $('#wrapper'),
middle = $('#middle'),
totalWidth = wrapper.width(),
middleWidth = middle.width(),
middleOuterWidth = middle.outerWidth(),
remainingWidth = totalWidth - middleOuterWidth,
sideWidth;
if(remainingWidth % 2 === 0){
// Remaining width is even, divide by two
sideWidth = remainingWidth/2;
} else {
// Remaining width is odd, add 1 to middle to prevent a half pixel
middle.width(middleWidth+1);
sideWidth = (remainingWidth-1)/2;
}
// Adjust the side width
$('.side').width(sideWidth);
}
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>
In the body of my site, I am trying to create two columns - one on the far right with a fixed width (300px) for advertisements etc, and one on the left which will take up the remaining space on the page. How can this be accomplished in CSS?
CSS :
.column-right {
float: left;
width: 100%;
height: 200px;
background-color: red;
}
.column-right .column-content {
margin-left: 250px;
}
.column-left {
float: left;
margin-left: -100%;
width: 250px;
height: 200px;
background-color: green;
}
HTML :
<div class="column-right">
<div class="column-content">
<strong>Right Column:</strong><em>Liquid</em>
</div>
</div>
<div class="column-left">
<strong>Left Column:</strong><em>250px</em>
</div>
Here is a tool to generate fixed liquid columns for placing adsense ads.
CSS:
#right-column{
width:300px;
float:right;
}
#other-column{
float:left;
width:100%;
padding-right:20px; /*to prevent text overlap as suggested in the comment*/
}
In HTML:
<div id='right-column'>
<!-- ads here -->
</div>
<div id='other-column'>
<!-- content here -->
</div>
You might also want to check out the YUI: CSS Grid Builder. It is a simple web interface where you specify what grid layout you are looking for, and they will provide you the html code you can use in combination with the YUI Grids CSS framework to get your desired layout. One nice thing about the YUI Grids CSS framework is it has good cross browser support which saves you time getting it to work across different browsers. You can also reverse engineer the code that you are provided from the grid builder to get some ideas on how you can do it on your own. The settings you will want to use with the YUI: CSS Grid Builder to get your desired layout is as follows:
Body Size: 100%
Body Columns: Sidebar right 300px
One solution I've found for this is to float the right column to the right and give the left column an absolute position with left:0 and right:300px. This will make it fluid as if you gave it a width:80%, but it will be relative to the parent container in a different way.
Here's an example:
http://jsfiddle.net/tkane2000/dp9GZ/
One issue you might find with this is that since it's absolute, it won't naturally push down the elements below it.
Another possible solution would be to give the left column
width:100%
padding-right: 300px;
and the right (fixed width) column:
position: absolute:
top:0;
right:0;
You might need to set box-sizing:border-box on the left column.
This also as some limitations. One that comes to mind, is that if you wanted the left column to have a border-right to separate each, the border would be on the wrong side of the right column.