Make unknown amount of divs fill nicely - html

Now, the title might be a bit vague, but I didn't know any other way to word it. What I basically want is this:
--------- --------- ---------
| DIV 1 | | DIV 2 | | DIV 3 |
--------- --------- ---------
--------- --------- ---------
| DIV 4 | | DIV 5 | | DIV 6 |
--------- --------- ---------
These div's are in a parent with a width of 1000px. So each div is 30% of width (with the proper gap inbetween basically).
The HTML:
<div id="matches">
<div class="match_box">
DIV 1
</div>
<div class="match_box">
DIV 2
</div>
<div class="match_box">
DIV 3
</div>
<div class="match_box">
DIV 4
</div>
<div class="match_box">
DIV 5
</div>
<div class="match_box">
DIV 6
</div>
</div>
The CSS:
#matches {
height: 100%;
width: 1000px;
}
How would I go about doing this? (.match_box being the div that need to flow nicely).
Thanks in advance!

If you don't have to target older browsers, you can use flexbox. This allows you to space the elements nicely. Here they go to the edges on both sides.
#matches {
height: 100%;
width: 500px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.match_box {
width:30%;
background-color: #eee;
margin-bottom: 10px;
}
https://jsfiddle.net/ekhts0fs/5/
Changing justify-content to space-between or center (see the link to flexbox above) can position them differently.

Try this:
#matches {
height: 100%;
width: 1000px;
}
.match_box {
width:30%;
float: left;
background-color: #ccc;
margin: 5px;
padding: 5px;
}
Live:
https://jsfiddle.net/Lu8p6gr3/2/

Related

Centering non-text content in a center division?

In my page, I need to make something that looks like this, with a center division with images of different widths all center-aligned within the division (the lines won't be visible, that's just to make it easier to explain):
---------------------------------------
| | IMAGE 1 | |
| <stuff> | IMAGE 2 | <stuff> |
| | IMAGE 123 | |
---------------------------------------
There's a parent division for the whole "pseudo-table", and three divisions for each pseudo-column. However, no matter what I try, it seems to always look like this, where the left edge of the images aligns with each other:
---------------------------------------
| | IMAGE 1 | |
| <stuff> | IMAGE 2 | <stuff> |
| | IMAGE 123 | |
---------------------------------------
My HTML looks like this:
<div class="parent">
<div class="leftcol">STUFF HERE</div>
<div class="centercol">
<img="URL HERE"><br>
<img="URL HERE"><br>
<img="URL HERE">
</div>
<div class="rightcol">STUFF HERE</div>
</div>
For my CSS, I have pared it down for the sake of troubleshooting to:
.parent {
display:flex;
justify-content:space-between;
}
.leftcol {
}
.centercol {
justify-items:center;
}
.rightcol {
}
I've also tried align-items:center to the same lack of results. Any ideas?
Add display: flex, align-items: center and flex-direction: column to the center column div:
.parent {
display:flex;
justify-content:space-between;
}
.leftcol {
}
.centercol {
display: flex;
align-items: center;
flex-direction: column;
}
.rightcol {
}
<div class="parent">
<div class="leftcol">STUFF HERE</div>
<div class="centercol">
<img src="https://picsum.photos/100"><br>
<img src="https://picsum.photos/150/100"><br>
<img src="https://picsum.photos/120/100">
</div>
<div class="rightcol">STUFF HERE</div>
</div>
You may also imbricate flex and grid to allow also X,Y centering on each columns : example
.parent {
display:flex;
}
.parent>div {
flex:1;
display:grid;
justify-content:center;
align-items:center;
gap:0.25em;/* optional */
}
/* see what is going on */
div div {
border:solid 1px;
background:linear-gradient(90deg,transparent 50%, rgba(200,100,100,0.1) 50%),linear-gradient(0deg,transparent 50%, rgba(100,0,100,0.1) 50%)
}
<div class="parent">
<div class="leftcol">STUFF HERE</div>
<div class="centercol">
<img src="https://picsum.photos/50"><br>
<img src="https://picsum.photos/50/40"><br>
<img src="https://picsum.photos/60/30">
</div>
<div class="rightcol">STUFF HERE</div>
</div>

Fill remaining width in first row instead if last row in CSS flexbox

I have container with multiline flexbox and some divs in it. If there is a different count of divs in the last row than in the other rows, divs will be larger because of flex-grow: 1. Is there any way to fill remaining width in the first row instead of last row?
| 1 | 2 | 3 | | 1 | 2 |
------------- -------------
| 4 | 5 | 6 | --> | 3 | 4 | 5 |
------------- -------------
| 7 | 8 | | 6 | 7 | 8 |
I don't know width of container, width of child div or count of children, so I cannot set width manually. Here is example.
section {
display: flex;
flex-wrap: wrap;
width: 10rem;
}
.reverse {
flex-wrap: wrap-reverse;
}
div {
height: 2.5rem;
width: 2.5rem;
background: lightblue;
margin: 0.2rem;
flex-grow: 1;
}
Corrent order, wrong layout:
<section>
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div>
</section>
Correct layout, wrong order:
<section class="reverse">
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div>
</section>
Add the below properties to first two div elements, basically 1 and 2.
flex-grow: 0;
flex-basis: 46%;
Or else you can use flex-wrap: wrap-reverse and explicitly define the order in reverse.
Here is a trick using nth-child combined with nth-last-child to target the first and second element. We basically have two cases where you need the first one to be full width or the first and second one half width:
section {
display: flex;
flex-wrap: wrap;
width: 10rem;
border:2px solid;
}
div {
height: 2.5rem;
width: 2.5rem;
background: lightblue;
margin: 0.2rem;
flex-grow: 1;
}
section > :nth-child(1):nth-last-child(3n + 1) {
flex-basis:100%
}
section > :nth-child(1):nth-last-child(3n + 2),
section > :nth-child(2):nth-last-child(3n + 1) {
flex-basis:40%
}
<section>
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div>
</section>
<section>
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div><div>8</div><div>9</div><div>10</div><div>11</div>
</section>
<section>
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div><div>7</div>
</section>
<section>
<div>1</div><div>2</div><div>3</div><div>4</div><div>5</div><div>6</div>
</section>
To me this seems like a good place to use CSS Grid when you're making a layout in two directions. You can try something like this:
.grid{
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-gap: .5rem;
}
.grid div{
width: 100%;
grid-column: span 2;
}
.grid div:nth-child(-n+2){
grid-column: span 3;
}

css to keep aspect ratio of 1:1 (square) based on parent height

I'm trying to make a calendar-like display where the dates' boxes are square-shaped but the whole calendar itself cannot have any scrolling..
it's supposed to look like this:
----------------------------------
| header element |
|--------------------------------|
| additional element |
|--------------------------------|
| ----------------- | --> start calendar (.box_fit-container)
| |sun|mon|tue|wed| |
| ----------------- |
| |d1 |d2 |d3 |d4 | |
| |d1 |d2 |d3 |d4 | |
| |d1 |d2 |d3 |d4 | | --> bottom of screen/viewport
| |d1 |d2 |d3 |d4 | | where it usually starts scrolling
| |d1 |d2 |d3 |d4 | |
| ----------------- |
----------------------------------
I managed to create the outer "frame" by using flex so that the outer container fills the remaining height of the original viewport, and I can also create an individual square shape, thanks to various SO contributors. but for whatever reason, I can't create a square shape where the object's width follows it's parent's height.
these are the code I have so far:
.box_fit-container {
display: flex;
flex-direction: column;
height: 80vh; /* this was supposed to be 100% according to the SO source I found, but since I'm working on a legacy code and there are other elements above this new one so I changed into 80vh to fit as close as possible */
}
.box_fit-header {
flex: 0 1 auto;
}
.box_fit-content {
flex: 1 1 auto;
}
.square-box {
position: relative;
width: 100%;
padding-top: 100%;
}
<div class="container">
<div class="box_fit-container">
<div class="box_fit-header">
<div>some header content
</div>
<div class="box_fit-content">
<!--
I need this .square-box elem to be square-shaped
but doesn't overflow outside the .box_fit-content
-->
<div class="square-box"></div>
</div>
</div>
</div>
If you can identify the height of the header or this one will always be fixed you can consider max-width to be 80vh - height of header
.box_fit-container {
display: flex;
flex-direction: column;
height: 80vh; /* this was supposed to be 100% according to the SO source I found, but since I'm working on a legacy code and there are other elements above this new one so I changed into 80vh to fit as close as possible */
border:1px solid;
}
.box_fit-header {
flex: 0 1 auto;
border:1px solid red;
}
.box_fit-content {
flex: 1 1 auto;
border:1px green;
}
.square-box {
position: relative;
width: 100%;
margin:auto;
max-width:calc(80vh - 25px);
border:2px solid;
}
.square-box:before {
content:"";
display:inline-block;
padding-top: 100%;
}
* {
box-sizing:border-box;
}
<div class="container">
<div class="box_fit-container">
<div class="box_fit-header">
<div>some header content
</div>
<div class="box_fit-content">
<!--
I need this .square-box elem to be square-shaped
but doesn't overflow outside the .box_fit-content
-->
<div class="square-box"></div>
</div>
</div>
</div>

Flow DIVs so that they use free space instead of just stacking

I got four divs.
Div two is half the height of div 1, div 3 & 4 is half the height of div 2.
On a large display the placement of the divs are fine:
---------------- ---------- -------- --------
| | | Div 2 | | Div 3| | Div 4 |
| Div 1 | |________| ------- -------
| |
| |
----------------
On smaller screens I want the following layout:
---------------- ----------
| | | Div 2 |
| Div 1 | |________|
| | | Div 3 |
| | ----------
---------------- | Div 4 |
i.e. div 3 and 4 are placed under div 2.
But instead they are placed under div 1:
---------------- ----------
| | | Div 2 |
| Div 1 | |________|
| |
| |
----------------
-------- --------
| Div 3| | Div 4 |
------- -------
Is it possible to get the second alternative in some way? In my own attempts I have never got both the large screen and the smaller screen alternatives to work with the same code.
You could use the CSS property flexbox (MDN reference) to achieve this. See the example below (in full screen and stretch your screen).
While starting mobile first, you can work your way up and with setting media queries, you can easily modify the visual hierarchy of the boxes. First, put a display: flex; on the wrapper div and then on the desired breakpoint (here 480px), add another display: flex; on the .inner-wrapper.
Note: this is just a quick setup and there are many ways to do this.
.wrapper {
width: 100%;
height: 100vh;
display: flex;
}
.inner-wrapper {
width: 50%;
}
.box-large {
width: 50%;
height: 50%;
}
.box {
width: 100%;
height: 25%;
}
.box-small {
width: 100%;
height: 12.5%;
}
#media screen and (min-width: 480px) {
.inner-wrapper {
display: flex;
}
}
/* Visual stuff */
body {
margin: 0;
padding: 0;
}
.box-one {
background-color: red;
}
.box-two {
background-color: blue;
}
.box-three {
background-color: green;
}
.box-four {
background-color: yellow;
}
<div class="wrapper">
<div class="box-one box-large">red</div>
<div class="inner-wrapper">
<div class="box-two box">blue</div>
<div class="box-three box-small">green</div>
<div class="box-four box-small">yellow</div>
</div>
</div>

Center a <span> relative to container div, align another span with right-aligned text left of it

I'm trying to align a span element in the center of a container div, and have another span with right-aligned text aligned left of it:
+--------------------------------------------------------+
| <div> |
+----------------------+----------+ |
| <span> | <span> | |
| | | |
| | | |
| | | |
| right-aligned | centered | |
| | | |
| | | |
| | | |
| | | |
+----------------------+----------+ |
| |
+--------------------------------------------------------+
The contents of both spans are dynamically generated, so I'd like to avoid any absolute pixel widths if possible.
Any idea how to achieve this type of layout?
Here is the markup I eventually went with based on Persinj's answer:
HTML
<nav class="navbar">
<span class="nav-aside">Right-aligned: </span>
<span class="nav-menu">centered</span>
<span class="nav-aside"></span>
</nav>
CSS
nav.navbar {
display: flex;
}
span.nav-aside {
flex-grow: 1;
flex-basis: 0;
text-align: right;
}
span.nav-menu {
align-self: center;
text-align: center;
}
I left the vendor prefixes out of my markup since I have limited browser requirements, and I'm relying on autoprefixer to take care of that. Please see the accepted answer if you need them.
Flexbox design / layout
This can be sloved using flex:
Setting tree boxes:
Aside, center and a hidden one, will fill the required space.
Setting a flex-grow will make make them take up different parts of the page.
Setting flex-grow: 1; on each will make them take up equal space.
Setting one of them to flex-grow: 0.5; will give this part less space to grow.
Adding a wrapper with the flex property we can use align-items:center to make sure they stay in the center of the wrapper.
Fiddle
.wrapper {
height: 250px;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-wrap: nowrap;
flex-direction: row;
align-items: center;
text-align: center;
}
.center,
.aside,
.not-shown {
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
}
.center {
flex-grow: 0.5;
background-color: lightblue;
height: 50px;
}
.aside {
text-align: right;
background-color: 1;
background: lightgreen;
height: 50px;
}
.not-shown {
visibility: hidden;
flex-grow: 1.5;
height: 50px;
}
<div class="wrapper">
<div class="aside">
aside
</div>
<div class="center">
center
</div>
<div class="not-shown">
</div>
</div>
HTML:
<div class="wrapper">
<span class="span-left">right-aligned</span>
<span class="span-center">centered</span>
</div>
CSS:
.span-left, .span-center { display: inline-block; }
.span-left {
width: 40%;
text-align: right;
}
.span-center {
width: 20%;
text-align: center;
}
Alternatively, use display: block and float: left; on your spans (don't forget to clear after the wrapper).