I have a layout design I was trying to accomplish via display:table-cell. This however may not be the best option, as it is causing me problems.
The desired outcome:
I wish that on smaller screens (less than 992px) to have a layout like so:
+----+----+
| | |
+----+----+
| |
+---------+
But then on larger screens (greater than 992px) to have this layout:
+--+--+--+
| | | |
+--+--+--+
The caveat is that they may not all have the same size content, and I want them to stretch vertically to all be the same height.
I am currently accomplishing this with :
.table {
width:100%;
display:table;
}
.cell {
display:table-cell;
width:50%;
position:relative;
padding:0px 10px;
border:1px solid #000;
}
My problem arises from the fact that in order to get the third cell to wrap around, I need to give it it's own row. But then, the cell will only spread to fit the first 50% (under the first cell) and not stretch 100%. This can be fixed by making the second row it's own table, but then, getting the two tables side-by-side at the right screen size is proving difficult as well.
If there is a better way to make the divs match height that would be ideal. I am using bootstrap, so using its grids would be easy, so long as I can make them all the same height.
Note: Faux columns do not work for my scenario as the backgrounds would not be appropriately colored/spaced.
You could simply use table-layout:fixed to ensure the cells to get equal width.
For the #media query part, use display:table-caption for the last cell, and set caption-side:bottom to specify the placement.
JSFiddle: http://jsfiddle.net/7kpcf46r/ (resize the output frame and see)
.table {
display: table;
table-layout: fixed;
border-collapse: collapse;
width: 100%;
}
.cell {
display: table-cell;
border: 1px solid red;
}
#media (max-width: 768px) {
.cell:last-child {
display: table-caption;
caption-side: bottom;
}
}
<div class="table">
<div class="cell">One Line</div>
<div class="cell">Two<br/>Lines</div>
<div class="cell">More<br/>Than two<br/>Lines</div>
</div>
You could use media queries to style contents based upon the width of the screen, for example, given the HTML:
<div class="cell"></div>
<div class="cell"></div>
<div class="cell"></div>
The CSS:
/* Setting the defaults, to apply regardless of
screen width: */
html, body {
/* removing margin and padding, setting
font-size to 0 in order to prevent
new-lines creating space between sibling
elements: */
margin: 0;
padding: 0;
font-size: 0;
}
/* resetting the font-size for all descendants of
the body element: */
body * {
font-size: 16px;
}
div.cell {
/* border-box, causes the browser to include
the width of the borders and padding within
the assigned width of the element: */
box-sizing: border-box;
/* instead of table-cell, causing elements
to default to displaying side-by-side: */
display: inline-block;
/* the default behaviour is to show at
50% of the width of the parent (body)
element: */
width: 50%;
margin: 0;
padding: 0;
height: 40vh;
border: 2px solid #000;
}
/*
Note: in this demo I'm using screen widths of
of 600px (min/max) to demonstrate the
principles within the constraints of JS Fiddle's
limited viewport. In your project, obviously, use
your required width of 992px.
*/
/* in screen-widths less than 600px
the last-child has a width of 100%: */
#media all and (max-width: 600px) {
div.cell:last-child {
width: 100%;
}
}
/* in screen-widths greater than 600px
div.cell elements have a width of 33%
(including the last-child) to display
side-by-side across the viewport: */
#media all and (min-width: 600px) {
div.cell {
width: 33%;
}
}
JS Fiddle demo.
References:
CSS Media Queries.
You can do it like this:
http://jsfiddle.net/z1kwrm8p/2/
HTML:
<div class="table">
<div class="cell" id="c1">ABCD</div><!--
--><div class="cell" id="c2">EFGH</div><!--
--><div class="cell" id="c3">XYZ PQRS ABCD EFGH IJKL MNOP QRSTUVWXYZ</div>
</div>
CSS:
.table {
width:100%;
display:block;
background:#009933;
}
.cell {
display:inline-block;
width:50%;
}
#c1 {
background:#99ccff;
}
#c2 {
background:#ff9966;
}
#c3 {
width:100%;
background:#66FF66;
}
#media only screen and (max-width: 991px) {
/* rules that only apply for canvases narrower than 992px */
.table {
display:table;
}
.cell {
display:table-cell;
width:33.3%;
}
#c3 {
width:33.3%;
}
}
Related
I would like to have layout of div elements that looks like below:
If screen is large enough then there is many blocks in the single row.
For example, I would like to have minimum width of each block set to 250px.
So on large screens I can have the following for such elements. On the right is the map (closable), if user hide it then there will be 6 blocks in the row.
Next when I shrink the browser window horizontally this all block doesn't fit in the row so they move to the next row. Ok this works now in that way that they go do second row, but they leave space between div blocks and the map. Like on the below image.
I would like to have such layout where if 4 blocks doesn't fit the space then ok there is 3 blocks but they equally fill the remaining space (without this remaining yellow space). See pictures below.
Then when browser windows shrinks more it should look like below
And on mobile devices and very narrow browser windows:
Ok I could achieve something like this using such CSS style:
#parent {
display: flex;
flex-wrap: wrap;
}
.child {
width: calc(33% - 15px);
margin-left: 10px;
margin-top: 10px;
margin-bottom: 20px;
min-width: 250px;
}
then I should manually change this using media queries:
calc(25% - 15px) //lg
calc(33% - 15px) //md
calc(50% - 15px) //sm
calc(100% - 15px) //xs
maybe even this when map disappears
calc(16.667% - 15px) //lg+no map
Ok FLEX isn't so backward-compatible so I could play even more and do something like this:
#parent {
}
.child {
width: calc(33% - 15px);
margin-left: 10px;
margin-top: 10px;
margin-bottom: 20px;
min-width: 250px;
float: left;
}
then also change this width depending on screen size manually
and add clear: left after last element using
.block-offer:nth-last-child(1):after {
clear: left;
}
or before other elements make some other clearfix
or even (is it necessery?) add clear: left after each row using:
.block-offer:nth-child(4n+1) {
clear:left;
}
.block-offer:nth-child(3n+1) {
clear:left;
}
.block-offer:nth-child(2n+1) {
clear:left;
}
.block-offer:nth-child(1n+1) {
clear:left;
}
like with this width: calc() depending on screen size and divs witdh
But then I need to use many media queries and I would like to wrap this CSS in some angular 2+ component and have there only such things like:
<blocks-container max-cols="6">
<block min-width="250px"></block>
<block min-width="250px"></block>
...
</blocks-container>
I think that using #media queries will improve a little this behaviour but my components will tightly coupled with screen size and I think there wasn't as generic as I would like them to be to flexibly specify max-cols and min-widths.
Here's one possible solution, which combines CSS flexbox and grid:
body {
display: flex; /* 1 */
}
article { /* 2 */
flex: 1; /* 2 */
margin-right: 10px;
display: grid; /* 3 */
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); /* 4 */
grid-auto-rows: 100px; /* 5 */
grid-gap: 10px; /* 6 */
}
map {
min-height: 200px; /* 7 */
width: 250px;
background-color: orangered;
}
#media (max-width: 800px) { /* 8 */
map { display: none; }
}
section {
background-color: lightblue;
border: 2px solid gray;
}
<article>
<section></section>
<section></section>
<section></section>
<section></section>
<section></section>
<section></section>
</article>
<map></map>
jsFiddle
Notes:
Create a flex container with two flex items.
The first item (article) holds the wrapping blocks (section). It's set to flex: 1 to consume all available width.
The first item is made into a grid container, so grid properties can be
applied to the blocks.
See below.
The grid-auto-rows property sets the height of automatically generated rows.
The grid-gap property is a shorthand for grid-column-gap and grid-row-gap. This rule set a 10px gap between grid items.
The second flex item is the map (map), which is aligned right due to flex: 1 on its sibling.
The media query removes the map, to simulate user behavior.
The auto-fill function allows the grid to line up as many grid tracks (columns or rows) as possible without overflowing the container. This can create similar behavior to flex layout's flex-wrap: wrap.
The minmax() function sets a minimum and maximum size range for a grid track. In the code above, the width of column tracks will be a minimum of 250px and maximum of whatever free space is available (1fr). This prevents the display of empty space.
The fr unit represents a fraction of the available space. It is similar to flex-grow in flex layout.
Browser Support for CSS Grid
Chrome - full support as of March 8, 2017 (version 57)
Firefox - full support as of March 6, 2017 (version 52)
Safari - full support as of March 26, 2017 (version 10.1)
Edge - full support as of October 16, 2017 (version 16)
IE11 - no support for current spec; supports obsolete version
Here's the complete picture: http://caniuse.com/#search=grid
You could refer this as an example, you could do that using flex or using media query to change style for elements at different break points as below, this gives more understanding of what changes are made.
Check this jsFiddle - https://jsfiddle.net/sjf5ms08/
#box{
width:100%;
height:auto;
}
#box > .b1, .b2, .b3, .b4, .b5, .b6{
width:33%;
height:150px;
background:red;
display:inline-block;
}
#media screen and (max-width: 1280px){
#box > .b1, .b2, .b3, .b4, .b5, .b6{
width:250px;
height:150px;
margin-bottom:10px;
background:blue;
}
}
#media screen and (max-width: 940px){
#box > .b1, .b2, .b3, .b4, .b5, .b6{
width:33%;
margin-bottom:10px;
background:yellow;
}
}
#media screen and (max-width: 760px){
#box > .b1, .b2, .b3, .b4, .b5, .b6{
width:49%;
margin-bottom:10px;
background:green;
}
}
<div id="box">
<div class="b1">1</div>
<div class="b2">2</div>
<div class="b3">3</div>
<div class="b4">4</div>
<div class="b5">5</div>
<div class="b6">6</div>
</div>
If you want to use the float method, you should do sth like :
FIDDLE
HTML:
<div class="col">
<div class="content">
<p>Content</p>
</div>
</div>
CSS:
/* complete with your style */
.col { display:block; width:25%; border-sizing:border:box; float:left; padding:10px; }
#media (max-width: 1280px) {
.col { width:33%; }
}
#media (max-width: 1024px) {
.col { width:50%; }
}
#media (max-width: 768px) {
.col { width:100%; }
}
If you want to use the flex method, order your html by row, then use flex-wrap:wrap; and width:250px or min-width:250px: width:25%, and play with the media queries as above
You can try applying flex on the cards (flex-grow/ flex-shrink/ flex-basis)
body {
margin: 0;
}
.parent {
width: 100vw;
min-height: 100vh;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.child:nth-child(2n+1) {
background: rgb(0, 0, 255);
}
.child:nth-child(2n+2) {
background: rgb(255, 255, 255);
}
.child:nth-child(2n+3) {
background: rgb(244, 241, 194);
}
.child {
margin: 10px 10px 20px 0;
min-width: 250px;
height: 300px;
background: green;
box-sizing: border-box;
border: 1px solid black;
flex: 1 1 250px;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
Fiddle : https://jsfiddle.net/0jc93hqn/
I have 3 boxes that are currently floated left of each other,
https://jsfiddle.net/2owu0k7s/
When viewing on a smartphone I want the width of the boxes to be near full screen, and the height of each box to be the same height has the viewport. Is this possible to do?
I have tried doing this within a media query,
.box {
float:none;
width:95%;
margin:0 auto 20px;
height:95%;
}
But on my iphone 6s I can still see more than 1 box and 5% of another.
When viewing on a smartphone I want the width of the boxes to be near full screen, and the height of each box to be the same height has the viewport. Is this possible to do?
With a media query and flexbox it is possible (and quite simple, in fact). Here's the smartphone view:
body {
display: flex;
flex-direction: column;
margin: 0;
padding: 0;
}
.box {
width: 100%;
height: 100vh;
box-sizing: border-box;
border: 3px solid red;
}
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
Revised Fiddle
.box {
width:350px;
height:50vh;
border:1px solid red;
float:left;
margin-right:10px;
}
#media screen and (max-width: 740px) {
.box {
float:none;
width:95%;
margin:0 auto 20px;
height:96vh;
}
}
Write an media query and
Give the height measurements using 'vh' -vertical height.
100vh means full screen-height.
How can I create a responsive arrangement of three divs, such that:
when the viewport is narrow, the three divs appear one atop the other
when the viewport is average, the first div appears full width atop the other two, which are side-by-side and have equal height
when the viewport is wide, the three divs appear side-by-side with equal height
I would like the solution to be broadly supported by browsers.
I've tried a number of media query based strategies, as follows:
To achieve #1, I style each div as display:block
To achieve #2, I style the green and blue divs as display:table-cell and created a container div styled with display:table.
However, if I create another container div for all three elements and style it with display:table, neither of the following approaches work:
Setting all divs to display:table-cell - because the red table cell and the other two are intervened by the smaller container div
Setting the red div and the smaller container divs to display:table-cell - because the smaller container div still needs to be set to display:table for the sake of the green and blue divs inside it.
It's all a bit hard to explain, but I guess you have the idea. Any help would be greatly appreciated.
Thanks!
Edit: I don't want to set the height of any div manually. It should be dictated by its content
What you are trying to achieve is fairly difficult using display: table because of just the issue you ran into: containers are required and the configuration is not that flexible due to the way tables' strict requirements.
I suggest you use flexbox which has fairly good browser coverage now: http://caniuse.com/#feat=flexbox
Here is a good example of how to get equal height rows using flexbox: http://osvaldas.info/flexbox-based-responsive-equal-height-blocks-with-javascript-fallback
I know #fauxserious already posted a very similar answer, but I'll post mine anyways because it's a bit different.
This doesn't use a table, nor the ::before or ::after CSS pseudo-elements.
div#div1 {
background-color: red;
}
div#div2 {
background-color: green;
}
div#div3 {
background-color: blue;
}
div {
box-sizing: border-box;
padding: 20px;
float: left;
margin: 1%;
width: 31%;
}
#media screen and (max-width: 750px) {
div#div1 {
width: 98%;
}
div#div2, div#div3 {
width: 48%;
}
}
#media screen and (max-width: 500px) {
div {
width: 98% !important;
}
}
<div id="div1"></div>
<div id="div2"></div>
<div id="div3"></div>
(It's best to see the above snippet if you open it in a new tab / window and resize it.)
See working example on JSFiddle.net.
EDIT See updated snippet. If you remove the height property of the divs (and replace it with padding so that you can see it even when it's empty), then the height will be determined by its content.
Edit: sorry I missed the equal height part.
You are trying to make squares so let me code and then explain. I'm going to make this a list to help identify things. Assume the ul has been reset (no margin, padding or style-type).
<ul>
<li>
<div>
</div>
</li>
<li>
<div>
</div>
</li>
<li>
<div>
</div>
</li>
</ul>
Here's the CSS to make everything squares.
li{
position:relative;
width:33%;
padding-top:33%;
}
li > div{
position:absolute;
top:0;
left:0;
right:0;
bottom:0;
height:100%;
width:100%;
}
You'll notice the padding to be equal to the width. Padding percentage no matter where it's used is based on the parent element's width (margin also works this way). Even if you use it on the top or bottom.
Now with that we can get to positioning with CSS
ul:before, ul:after{
content:"";
display:table;
}
ul:after{
clear:both;
}
li{
position:relative;
width:33%;
padding-top:33%;
float:left;
}
#media screen and (max-width:800px){
li{
width:50%;
padding-top:50%;
}
li:first-child{
width:100%;
padding-top:0; /* Not sure what height you'd want here*/
}
}
#media screen and (max-width:400px){
li{
width:100%;
padding-top:100%;
}
}
I was unsure of why you wanted to use display: table;, however I did something a little different but will look like the images you posted above.
HTML:
<div class="container">
<div class="box box1"></div>
<div class="box box2"></div>
<div class="box box3"></div>
</div>
CSS:
.container {
width: 90%;
margin: 0 auto;
}
.box {
width: 32.3333%;
float: left;
height: 200px;
margin: .5%;
}
.box1 {
background-color: #ff4034;
}
.box2 {
background-color: #22ff62;
}
.box3 {
background-color: #24a6ff;
}
#media screen and (max-width: 900px){
.box:first-child {
width: 99%;
}
.box:nth-child(n + 2){
width: 49%;
}
}
#media screen and (max-width: 436px){
.container .box {
width: 99%;
clear: both;
margin-bottom: 10px;
}
}
Result: Your images above
How about using flex?
.parent {
border: 1px solid #555;
display: flex;
flex-flow: row wrap;
}
.dual {
display: flex;
flex-flow: row wrap;
flex: 2 2 550px;
}
.item {
padding: 20px;
margin: 10px;
flex: 1 1 200px;
min-width: 200px;
}
<div class="parent">
<div class="item" style="background-color: red">red</div>
<div class="dual">
<div class="item" style="background-color: green; flex: 1 1 100px">green</div>
<div class="item" style="background-color: blue; flex: 1 1 100px">blue</div>
</div>
</div>
I had to tweak the sizes a little due to padding and margins, like ".dual" being 550px instead of 400px. Also if the combined items are the same size they will show as two rows in the second column sometimes when shrinking so I made them smaller. Make it full page when you run the snippet or check out the fiddle link which is easier to resize has some extra text showing the blue and green boxes keep the same height in layout 2.
I guess I have the simplest problem ever and cannot find a ready solution.
I need to make a grid of square items with fixed widths and heights and fixed distance between them.
I need three columns maximum, and during browser resizing I would need this grid to shrink to two, and then one column (items must always keep their size and distance between them).
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?
Just a random simple mock-up for a page with a bunch of squares, resize result at will:
http://jsfiddle.net/cuAfg/
HTML:
<div class="container">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
/* etc */
</div>
CSS:
.container {
width: 960px;
margin: auto;
overflow: auto;
}
#media only screen and (max-width : 960px) {
.container {
width: 640px;
}
}
#media only screen and (max-width : 640px) {
.container {
width: 320px;
}
}
.block {
width: 300px;
height: 300px;
float:left;
margin: 10px;
background: #ccc;
}
if your blocks have a known width and horizontal margins, you can set a maw-width on parent container to allow maximum 3 of them per lines.
For instance, a 200px square boxe with 40px margin around, 900px of width would allow 3 of them, the fourth will go down.
Once it shrinks, only 2 are left and so on.
Demos with float, inline-block or flex .You may set a min-width too if you like.
Method used does not really matters here :) .
CODEPEN
html,
<div class="container">
<div class="inner-container">
<div class="box">a</div>
<div class="box">b</div>
<div class="box">c</div>
</div>
</div>
and the css,
* {
-webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-moz-box-sizing: border-box; /* Firefox, other Gecko */
box-sizing: border-box;
text-align: center;
}
.container {
/* width = 200 * 3 + 25 * 2 = 650 */
float: left;
position: relative;
left: 50%;
}
.inner-container {
float:left;
position: relative;
left: -50%;
}
.container::after {
content: '';
display: block;
clear: both
}
.box {
float: left;
background-color: blue;
width: 200px;
height: 200px;
margin-right: 25px;
margin-bottom: 25px;
display: inline-block
}
.box:last-child {
margin-right: 0
}
this way, a b and c will retain its original width and height. When the container does not have sufficient width, c will go down, then b.
There are a couple of techniques. Since your question is vague I can only cover them in general terms.
First you start with a fixed with:
width: <number>px;
Then to create columns you can do:
display: inline-block;
Or
float: left;
If you go with floats you may need to overflow: auto on the main container so the main layout doesn't collapse.
Problem:
I want to center the containing div, but I want to also left-align the blocks.
I think flex boxes might be the solution, but I'm not sure what to do with them.
I want to do this:
without Javascript
without tables
without setting a row width (the row width must be dynamic.. that's the intent of this exercise)
without setting a width to the container. (same as setting a row width)
without adding invisible divs. (same as setting a row width)
Example, with current CSS (attempt failed):
.block {
border : 5px solid DarkRed;
width : 150px;
height : 150px;
display : inline-block;
}
.container {
display : inline-block;
text-align : center;
}
http://jsfiddle.net/SKRjG/
Edit: here is a Javascript version to show how it should look like:
http://jsfiddle.net/SKRjG/8/
Put your divs within another container so that it looks like
<div class="container">
<div class="subcontainer">
<div class="Block"></div>ETC
</div>
</div>
Then have #media queries to change the width of .subcontainer to fit your blocks into perfect grids. Then center your .subcontainer div with margin: 0 auto;
Css might look like:
.block {
border : 5px solid DarkRed;
width : 150px;
height : 150px;
display : inline-block;
}
.subcontainer {
text-align:left;
margin:0 auto;
}
/*Three columns*/
#media (min-width: 495px){
.subcontainer{width:495px;}
}
/*Four columns*/
#media (min-width: 660px){
.subcontainer{width:660px;}
}
/*Five*/
#media (min-width: 825px){
.subcontainer{width:825px;}
}
Fiddle: http://jsfiddle.net/TM2wB/26/
Use this CSS
.block {
border : 5px solid DarkRed;
width : 150px;
height : 150px;
display : inline-block;
float:left;
clear:both;
}
.container {
display : inline-block;
text-align :center;
margin:0 auto;
}