Div spacing offset using calc() - html

I have 3 vertical rows which are divided on my screen using calc()
I'm using JS to set the height for each box type
width: calc(1/3 * 100%);
This is the javascript to set the height of each block, It's setting the height equal to the width
and in the case of a long box it's setting the height to half the width.
$('.box1').height( $('.box1').width() );
$('.box2').height( $('.box2').width() / 2 );
$('.box4').height( $('.box4').width() );
I have a weird offset between the columns in the row ( see screenshot )
You can view the page here http://cloudlabme.webhosting.be/4sr
This is the HTML of the two vertical rows
<div class="container">
<div class="row">
<div class="box box4 box-event" style="background-image: url(build/img/events/2.jpg)"><h1>II</h1></div>
<div class="box box2 box-medium"></div>
</div>
<div class="row">
<div class="box box2 box-light"></div>
<div class="box box1 box-dark"><h3>Hier</h3></div>
<div class="box box1 box-medium"></div>
<div class="box box2"></div>
</div>
</div>
This is my CSS
.container {
position: relative;
width: 100%;
max-width: $breakpoint;
margin: 0 auto;
z-index: 0;
}
.row {
float: left;
width: calc(1/3 * 100%);
background: #f2f2f2;
}
/* BOX */
.box {
&.box-light {background: #fff;}
&.box-medium {background: #666;}
&.box-dark {background: #111;}
}
.box1 {
float: left;
width:50%;
background: #ff4444;
}
.box2 {
clear: left;
width: 100%;
background: #ff6666;
}
.box4 {
clear: left;
width: 100%;
background: #ff8888;
}
Thanks! This is killing my brain!

Most probably, the one pixel gap is caused by rounding off error. The only solution I could think of is to force the container width to be a multiple of 3 using JavaScript.
A better solution is to use CSS table display. Set 33.33333333% width on the first two "cells" and let the third one autosize itself. The heights will still be off by one or two pixel but this is better than using calc() and fighting with rounding issues.
$(window).on("load resize", function() {
$('.box1').height($('.box1').width());
$('.box2').height($('.box2').width() / 2);
$('.box4').height($('.box4').width());
});
.container {
display: table;
width: 100%;
}
.row {
display: table-cell;
vertical-align: top;
background: #CCC;
}
.row:first-child, .row:first-child + .row {
width: 33.33333333%;
}
.box1 {
float: left;
width: 50%;
background: #C99;
}
.box2 {
clear: left;
background: #C66;
}
.box4 {
clear: left;
background: #C33;
}
h1, h3 {
margin: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="container">
<div class="row">
<div class="box box4">
<h1>II</h1>
</div>
<div class="box box2"></div>
</div>
<div class="row">
<div class="box box2"></div>
<div class="box box1">
<h3>Hier</h3>
</div>
<div class="box box1"></div>
<div class="box box2"></div>
</div>
<div class="row">
<div class="box box2"></div>
<div class="box box4"></div>
</div>
</div>

Related

Row with 3 columns of fixed and flexible widths

I need to create three columns in a row where the right item has a min-width: 300px and the middle item has a fixed width of 595px. The left item has to use the rest of the width! I've tried to use flexbox and table cell but the left container seems to exceed the screen width which causes bottom scrollbar to appear, which is not wanted in this case.
<div class="row">
<div class="column left">
</div>
<div class="column middle">
</div>
<div class="column right">
</div>
</div>
.row {
width: 100%;
& .column {
&.left {
}
&.middle {
width: 595px !important;
}
&.right {
min-width: 300px;
}
}
}
Based on your requirements, you're going to get a horizontal scrollbar when the screen width is less than 895px. That's the length of your width: 595px and min-width: 300px containers.
.row {
display: flex;
height: 100px;
}
.left {
flex: 1; /* consume remaining space */
background-color: aqua;
}
.middle {
flex: 0 0 595px; /* equivalent to width: 595px; flex-grow, flex-shrink, flex-basis */
background-color: orange;
}
.right {
min-width: 300px;
background-color: lightgreen;
}
<div class="row">
<div class="column left"><code>flex: 1</code></div>
<div class="column middle"><code>width: 595px</code></div>
<div class="column right"><code>min-width: 300px</code></div>
</div>
jsFiddle demo

How to use flexbox inside a fixed container?

I have a div that is position: fixed; within the viewport. Within this are a series of child elements that use display: flex; and I need a scrollable element to fill 100% of the height of the flexed element. The problem I am having is that because done of the parent elements of the scrollable element have a fixed height, so the scrollable element just pushed the bottom of the flexed element rather than scroll.
Please see the following JSBin example. In this example, the blue block needs to extend to 100% the height of the red block, with the contents of the blue block still being scrollable. Needs to work in IE10+, latest Firefox and Chrome:
https://jsbin.com/terimim/edit?html,css,output
There are two primary issues causing the layout problem. They are each explained here:
Why doesn't flex item shrink past content size?
Chrome / Safari not filling 100% height of flex parent
revised demo
* {
box-sizing: border-box;
min-height: 0;
}
body {
background-color: #eaeaea;
}
#menu {
background-color: #fff;
position: fixed;
top: 20px;
right: 20px;
left: 20px;
bottom: 20px;
padding: 0;
z-index: 12;
height: calc(100vh - 40px);
}
#menu-contents {
display: flex;
flex-direction: column;
height: 100%;
}
#menu-pane-wrapper {
display: flex;
flex: 1;
background-color: #eeffcc;
}
#menu-panes {
flex: 1;
display: flex;
}
.menu-pane {
box-sizing: border-box;
background-color: #ff0000;
width: 20%;
padding: 10px;
display: flex;
}
.menu-pane-overflow {
flex: 1;
overflow-x: hidden;
overflow-y: scroll;
background-color: aqua;
}
.menu-item {
padding: 5px;
}
<div id="menu">
<div id="menu-contents">
<div id="menu-header">HEADER</div>
<div id="menu-pane-wrapper">
<div id="menu-panes">
<div class="menu-pane">
<div class="menu-pane-overflow">
<div class="menu-pane-scroll">
<div class="menu-item">1</div>
<div class="menu-item">2</div>
<div class="menu-item">3</div>
<div class="menu-item">4</div>
<div class="menu-item">5</div>
<div class="menu-item">6</div>
<div class="menu-item">7</div>
<div class="menu-item">8</div>
<div class="menu-item">9</div>
<div class="menu-item">10</div>
<div class="menu-item">11</div>
<div class="menu-item">12</div>
<div class="menu-item">13</div>
<div class="menu-item">14</div>
<div class="menu-item">15</div>
<div class="menu-item">16</div>
<div class="menu-item">17</div>
<div class="menu-item">18</div>
<div class="menu-item">19</div>
<div class="menu-item">20</div>
<div class="menu-item">21</div>
<div class="menu-item">22</div>
<div class="menu-item">23</div>
<div class="menu-item">24</div>
<div class="menu-item">25</div>
<div class="menu-item">26</div>
<div class="menu-item">27</div>
<div class="menu-item">28</div>
<div class="menu-item">29</div>
<div class="menu-item">30</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

Bootstrap: Change container order on small screens

I'm facing a bootstrap problem.
In my html page, I used different containers but I'm not able to re-arrange and re-organize them as I want in mobile screens.
Here my Bootply.
And to be more clear, I want it to look like this:
Containers 1 and 5 are fluid, instead 2, 3, 4 are not.
How can I move container 1 and 2 after 3 and 4 in small screens?
Thank you in advance for your reply!
Cheers!
This is not possible without rearranging your content.
One way is to make two versions of the area you want to rearrange and hide them based on the width of the browser. This is bad practice, especially if you have a whole website you want to rearrange on resize, but for a small div with 5 divs inside it would be an acceptable solution.
Here is the adapted HTML
<div class="desktopwrapper"> <!-- added a desktop wrapper -->
<div class="container-fluid green"></div>
<div class="container red"></div>
<div class="container ">
<div class="row">
<div class="col-sm-8 yellow"></div>
<div class="col-sm-4 fuxia"></div>
</div>
</div>
<div class="container-fluid blue"></div>
</div>
<div class="mobilewrapper"> <!-- added a mobile wrapper and rearranged content -->
<div class="container ">
<div class="row">
<div class="col-sm-8 yellow"></div>
<div class="col-sm-4 fuxia"></div>
</div>
</div>
<div class="container-fluid green"></div>
<div class="container red"></div>
<div class="container-fluid blue"></div>
</div>
And I have added these lines to CSS:
#media screen and (max-width: 766px) {
.desktopwrapper {
display:none;
}
}
#media screen and (min-width: 767px) {
.mobilewrapper {
display:none;
}
}
What this basically does, is hide one arrangement when the screen gets resized to 766px wide and will display the other. And of course the other way around.
You can try it out here.
Another way would be to put everything in a wrapper, position the wrapper relative, all the divs inside absolute and just place them with using px. This is however really not useful when divs have changing heights depending on the content. The best way would be to do like the example I have.
flexbox proof of concept.
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
color: white;
text-align: center;
}
body {
height: 100%;
}
h2 {
display: inline-block;
background: #000;
padding: .25em;
}
.page {
min-height: 100%;
display: flex;
flex-direction: column;
}
header {
flex: 0 0 75px;
background: darkgreen;
}
.banner {
flex: 0 0 100px;
width: 80%;
margin: auto;
background: darkred;
}
main {
flex: 1;
width: 80%;
margin: auto;
display: flex;
}
.content {
width: 75%;
background: yellow;
}
aside {
width: 25%;
background: fuchsia;
}
footer {
flex: 0 0 100px;
background: lightblue;
}
#media screen and (max-width: 768px) {
.banner,
main {
width: 100%;
}
main {
flex-direction: column;
order: -1;
}
.content,
aside {
flex: 1;
width: 100%;
}
aside {
flex: 0 0 150px
}
}
<div class="page">
<header>
<h2>1</h2>
</header>
<div class="banner">
<h2>2</h2>
</div>
<main>
<div class="content">
<h2>3</h2>
</div>
<aside>
<h2>4</h2>
</aside>
</main>
<footer>
<h2>5</h2>
</footer>
</div>
Codepen Demo

Center align HTML Elements, while adding new items from left

I have a parent div containing an unknown number of smaller divs that are used like large icon-like buttons. If a row of child divs is full, I would like them to have equal margins on each side (ie. centered), but if a row is not full I would like them to be filled in from the left side (but still in columns with the elements above). Is there a way to do this with CSS? Resizing the window should maintain the centering and add/remove columns as necessary. All the child div widths are known.
Here's a crappy image of the behavior I'm trying for:
Okay I figured out a solution for this that both allows for equal margins and ALSO aligns divs left in the last row. The caveat is that it uses hidden elements, so the container is taller than the visible elements it contains.
Also it adds a bunch of extra markup to your code. If I thought of any other way to do this, I would do it differently. Sorry.
JSFiddle: https://jsfiddle.net/88qadmo3/2/
#container > div {
margin: 10px;
width: 100px;
height: 100px;
}
.floatleft {
background-color: red;
}
.invis {
visibility: hidden;
}
#container {
display: flex;
flex-wrap: wrap;
justify-content: center;
background-color: #DDDDDD;
}
.clearfix {
clear: both;
}
<div id="outer">
<div id="container">
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="floatleft"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
<div class="invis"></div>
</div>
</div>
You can do this by wrapping each of the child elements in an element and using CSS media queries to change the size of the wrappers. Then, just use % width on the wrappers based on what you want the column sizes to be.
When you run the example, shrink it to <400px so you can see it move from 6 columns to 3 (you'll need to run the code snippet on a full-page to see this).
.parent {
border: 2px solid red;
}
.child {
width: 100px;
display: block;
margin: 0 auto;
border: 1px solid black;
}
.wrapper {
display: inline-block;
text-align: center;
float: left;
width: 16.66%;
margin: 0;
padding: 0;
box-sizing: border-box;
}
.clear {
clear: both;
}
#media (max-width: 800px) {
.wrapper {
width: 20%;
}
}
#media (max-width: 600px) {
.wrapper {
width: 25%;
}
}
#media (max-width: 400px) {
.wrapper {
width: 33.33%;
}
}
<div class="parent">
<div class="wrapper">
<div class="child">1</div>
</div>
<div class="wrapper">
<div class="child">2</div>
</div>
<div class="wrapper">
<div class="child">3</div>
</div>
<div class="wrapper">
<div class="child">4</div>
</div>
<div class="wrapper">
<div class="child">5</div>
</div>
<div class="wrapper">
<div class="child">6</div>
</div>
<div class="clear"></div>
</div>
Just use float left, and items of the width (the original fiddle):
<div class="container">
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
<div class="item">Cats</div>
</div>
.container {
overflow: auto;
}
.item {
width: 50px;
float: left;
margin: 0 10px;
}

Combine divs with percentage width with margin in pixels

I have a page with multiple items, which have a 33.33% width to fill up the complete width of the page. However, I want to add a 20px margin between the items (both vertically and horizontally, but vertically is the problem here), but just adding a 20px margin on the right of each 1st and 2nd item in a row, destroys the complete page. (remove the commented-out CSS from the fiddle to see what I mean).
JSfiddle
Now, the question: How do I add a 20px margin and make sure all .item divs keep the same size? I could play with the percentage of the width and adding the removed width of an .item as a margin, but this would never be a steady 20px, since, well, it's percentages.
HTML
<div id="main">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
</div>
CSS
#main .item {
height: 100px;
width:33.33%;
float:left;
text-align: center;
}
#main .item:nth-child(3n+1) {
background: red;
}
#main .item:nth-child(3n+3) {
background: yellow;
}
#main .item:nth-child(3n+2) {
background:lightblue;
}
/*.item:nth-child(3n+1), .item:nth-child(3n+2) {
margin-right: 20px !important;
}*/
You could use calc() to subtract the 20px from 33.33%.
In this case, you would use width: calc(33.33% - 20px) to displace the margins.
Updated Example
#main .item:nth-child(3n+1),
#main .item:nth-child(3n+2) {
width: calc(33.33% - 20px);
margin-right: 20px;
}
Unfortunately, this will result in elements of differing widths (since the 20px isn't being subtracted from all the elements). A better solution would be to subtract 13.33px from all the elements (40px/3px):
Updated Example
#main .item {
height: 100px;
width: calc(33.33% - 13.33px);
float:left;
text-align: center;
}
Change the width of each .item class and calculate it using the calc()
#main .item {
height: 100px;
width:calc(33.33% - 20px);
float:left;
text-align: center;
}
Fiddle
You can use % for wrapper and change margin to padding while using box-sizing: border-box
.wrapper {
/* enable to add padding to width */
box-sizing: border-box;
width: 33.33%;
float: left;
padding: 20px;
background-color: #EFEFEF;
}
.item {
background-color: #ddd;
padding: 5px;
}
<div class="wrapper">
<div class="item">Some thext here</div>
</div>
<div class="wrapper">
<div class="item">Some thext here</div>
</div>
<div class="wrapper">
<div class="item">Some thext here</div>
</div>