I'm trying to fill my page horizontally with as many blocks as possible and center the result.
I want the grid to be able to resize when the window becomes smaller:
wide window
xxx
small window
xx
x
Is this possible to achieve without javascript?
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
To explain the desired centering visually:
Can the yellow highlighted area be evenly distributed on either side?
The desired box alignment:
This only works in chrome for some reason.
Auto-fit and auto-fill needs a known width to calculate from, we can do that with max-width:100% instead of using width which will stretch it and prevent us from centering, and avoid fixed widths.
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
max-width: 100%;
}
.center {
display: flex;
flex-direction: column;
align-items: center;
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
There is a quirk with this, if you start with a wide viewport then resize it to a smaller one, the grid won't be centerd because of auto-fill
Say you have 3 elements but the container can fit 4 with auto-fill it will create a forth column but we have no forth element so it will look unevenly spaced.
I suggest using auto-fit, which instead of creating the forth column it will split the space evenly on each side.
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, 200px);
max-width: 100%;
}
.center {
display: flex;
flex-direction: column;
align-items: center;
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
Now if you resize the window enough you'll see sometimes it's not evenly spaced that's because of the relative unit on the max-width, it need to recalculate the width because it's based on the parent and parent's width which is based on the content.
we can trigger that recalculation using an animation.
chrome specific solution
.center {
display: flex;
flex-direction: column;
align-items: center;
}
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, 200px);
max-width: 100%;
animation: recalc 5s linear infinite;
}
#keyframes recalc {
to {
max-width: 99.9%;
}
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
To support at least FF and maybe some other browsers, use viewport units.
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, 200px);
max-width: 100vw;
margin:0 auto;
}
.center {
display: flex;
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
Try this with flexbox.
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: flex;
justify-content: center;
align-items: center;
}
#media screen and (max-width: 767px) {
.grid {
flex-wrap: wrap;
justify-content: center;
}
.box {
width: 50%
}
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
I wouldn't use grid for this. Use flex:
*{
box-sizing:border-box; padding:0; margin:0; font-size:0;
}
html,body{
width:100%; height:100%; background:#ccc;
}
.box{
width:200px; height:150px; background-color:white; border:6px solid red;
}
.box:nth-child(2n+2) {
background-color:blue;
}
.center,.grid{
display:flex; align-items:center; justify-content:center; height:100%;
}
.grid{
min-width:600px; flex-wrap:wrap; align-items:center;
}
<div class='center'>
<div class='grid'>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
<div class='box'></div>
</div>
</div>
Yes, you can centre an auto-fill, left-aligned grid (and it works in Firefox).
To do this, you just need justify-content: center; on the grid container, which would give you this:
A good example of this (and why it works) is on the MDN docs page for justify-content
Your example would look like this:
.box {
box-sizing: border-box;
width: 200px;
height: 150px;
background-color: white;
border: solid 6px red;
}
.box:nth-child(2) {
background-color: blue
}
.grid {
display: grid;
grid-template-columns: repeat(auto-fill, 200px);
justify-content: center; /* <-- This is all you need to add */
}
<div class="center">
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
It's worth noting though, that when you only have one row of boxes, they may not be centred, since the repeat function will create empty columns to fill the row, effectively left aligning the actual boxes:
Related
i trying to make train rails,
there is option to make infinite vertical lines without duplicate the rail_line div infinite times?
this is my code that i tried:
html,
body {
margin: 0;
padding: 0;
}
b,
strong {
font-weight: 700;
}
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
#rails {
display: flex;
flex-direction: column;
}
#rails .lines {
display: flex;
flex-direction: column;
gap: 10px;
}
#rails .lines .line {
background: #000000;
height: 1px;
width: 100%;
}
#rails .rail {
display: flex;
flex-direction: row;
gap: 40px;
height: 85px;
overflow: hidden;
}
#rails .rail .rail_line {
width: 1px;
background: #000000;
transform: rotate(17deg);
height: calc(100% + 4px);
top: -2px;
position: relative;
}
<div id="rails">
<div class="lines">
<div class="line"></div>
<div class="line"></div>
</div>
<div class="rail">
<div class="rail_line"></div>
<div class="rail_line"></div>
<div class="rail_line"></div>
<div class="rail_line"></div>
<div class="rail_line"></div>
<div class="rail_line"></div>
<div class="rail_line"></div>
<div class="rail_line"></div>
</div>
<div class="lines">
<div class="line"></div>
<div class="line"></div>
</div>
</div>
I can duplicate it with PHP \ JS but i want CSS option without create a lot of DOM elements
i put 8 lines for example but i want it responsive for each page width
TNX
#test {
height: 70px;
background-image:
repeating-linear-gradient(
-80deg,
transparent 0px,
/* 0.5 transparent-black blur, optional */
black 0.5px,
/* 1px black line (total ~=1.5) */
black 1.5px,
/* 0.5 black-transparent blur, optional */
transparent 2px,
transparent 50px
);
border-top: 2px solid black;
border-bottom: 2px solid black;
}
<div id="test"></div>
I'm using a flex box to display 8 items that will dynamically resize with my page. How do I force it to split the items into two rows? (4 per row)?
Here is a relevant snip:
(Or if you prefer jsfiddle - http://jsfiddle.net/vivmaha/oq6prk1p/2/)
.parent-wrapper {
height: 100%;
width: 100%;
border: 1px solid black;
}
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin: -10px 0 0 -10px;
}
.child {
display: inline-block;
background: blue;
margin: 10px 0 0 10px;
flex-grow: 1;
height: 100px;
}
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
You've got flex-wrap: wrap on the container. That's good, because it overrides the default value, which is nowrap (source). This is the reason items don't wrap to form a grid in some cases.
In this case, the main problem is flex-grow: 1 on the flex items.
The flex-grow property doesn't actually size flex items. Its task is to distribute free space in the container (source). So no matter how small the screen size, each item will receive a proportional part of the free space on the line.
More specifically, there are eight flex items in your container. With flex-grow: 1, each one receives 1/8 of the free space on the line. Since there's no content in your items, they can shrink to zero width and will never wrap.
The solution is to define a width on the items. Try this:
.parent {
display: flex;
flex-wrap: wrap;
}
.child {
flex: 1 0 21%; /* explanation below */
margin: 5px;
height: 100px;
background-color: blue;
}
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
With flex-grow: 1 defined in the flex shorthand, there's no need for flex-basis to be 25%, which would actually result in three items per row due to the margins.
Since flex-grow will consume free space on the row, flex-basis only needs to be large enough to enforce a wrap. In this case, with flex-basis: 21%, there's plenty of space for the margins, but never enough space for a fifth item.
Add a width to the .child elements. I personally would use percentages on the margin-left if you want to have it always 4 per row.
DEMO
.child {
display: inline-block;
background: blue;
margin: 10px 0 0 2%;
flex-grow: 1;
height: 100px;
width: calc(100% * (1/4) - 10px - 1px);
}
Here is another apporach.
You can accomplish it in this way too:
.parent{
display: flex;
flex-wrap: wrap;
}
.child{
width: 25%;
box-sizing: border-box;
}
Sample:
https://codepen.io/capynet/pen/WOPBBm
And a more complete sample:
https://codepen.io/capynet/pen/JyYaba
I would do it like this using negative margins and calc for the gutters:
.parent {
display: flex;
flex-wrap: wrap;
margin-top: -10px;
margin-left: -10px;
}
.child {
width: calc(25% - 10px);
margin-left: 10px;
margin-top: 10px;
}
Demo: https://jsfiddle.net/9j2rvom4/
Alternative CSS Grid Method:
.parent {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 10px;
grid-row-gap: 10px;
}
Demo: https://jsfiddle.net/jc2utfs3/
For more detail you can follow this Link
.parent{
display: flex;
flex-wrap: wrap;
}
.parent .child{
flex: 1 1 25%;
/*Start Run Code Snippet output CSS*/
padding: 5px;
box-sizing: border-box;
text-align: center;
border: 1px solid #000;
/*End Run Code Snippet output CSS*/
}
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
<div class="child">7</div>
<div class="child">8</div>
</div>
I believe this example is more barebones and easier to understand then #dowomenfart.
.child {
display: inline-block;
margin: 0 1em;
flex-grow: 1;
width: calc(25% - 2em);
}
This accomplishes the same width calculations while cutting straight to the meat. The math is way easier and em is the new standard due to its scalability and mobile-friendliness.
.parent-wrapper {
height: 100%;
width: 100%;
border: 1px solid black;
}
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin-right: -10px;
margin-bottom: -10px;
}
.child {
background: blue;
height: 100px;
flex-grow: 1;
flex-shrink: 0;
flex-basis: calc(25% - 10px);
}
.child:nth-child(even) {
margin: 0 10px 10px 10px;
background-color: lime;
}
.child:nth-child(odd) {
background-color: orange;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
</style>
</head>
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
</html>
;)
Flex wrap + negative margin
Why flex vs. display: inline-block?
Flex gives more flexibility with elements sizing
Built-in white spacing collapsing (see 3 inline-block divs with exactly 33% width not fitting in parent)
Why negative margin?
Either you use SCSS or CSS-in-JS for the edge cases (i.e. first element in column), or you set a default margin and get rid of the outer margin later.
Implementation
https://codepen.io/zurfyx/pen/BaBWpja
<div class="outerContainer">
<div class="container">
<div class="elementContainer">
<div class="element">
</div>
</div>
...
</div>
</div>
:root {
--columns: 2;
--betweenColumns: 20px; /* This value is doubled when no margin collapsing */
}
.outerContainer {
overflow: hidden; /* Hide the negative margin */
}
.container {
background-color: grey;
display: flex;
flex-wrap: wrap;
margin: calc(-1 * var(--betweenColumns));
}
.elementContainer {
display: flex; /* To prevent margin collapsing */
width: calc(1/var(--columns) * 100% - 2 * var(--betweenColumns));
margin: var(--betweenColumns);
}
.element {
display: flex;
border: 1px solid red;
background-color: yellow;
width: 100%;
height: 42px;
}
you can try this
.parent-wrapper {
height:100%;
width:100%;
border: 1px solid black;
}
.parent {
display: grid;
font-size: 0;
grid-template-columns: 25% 25% 25% 25%;
}
.child {
background:blue;
flex-grow: 1;
height:100px;
margin: 10px;
margin-bottom: 0;
}
.child:last-child {
margin-bottom: 10px;
}
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
https://jsfiddle.net/samet19/gdntwLhb/
Here's another way without using calc().
// 4 PER ROW
// 100 divided by 4 is 25. Let's use 21% for width, and the remainder 4% for left & right margins...
.child {
margin: 0 2% 0 2%;
width: 21%;
}
// 3 PER ROW
// 100 divided by 3 is 33.3333... Let's use 30% for width, and remaining 3.3333% for sides (hint: 3.3333 / 2 = 1.66666)
.child {
margin: 0 1.66666% 0 1.66666%;
width: 30%;
}
// and so on!
That's all there is to it. You can get fancy with the dimensions to get a more aesthetic sizes but this is the idea.
How to create 3 divs side by side using flex where middle div can (grow&shrink) in respect to other two divs?
I want to create Three divs A B C with a parent containing flex css property. Having A fixed width of 300px and C having min width 200px and can grow in width as more content is added.
While B should be in between A and C should grow and shrink automatically as per the widths of A and C.
Although A and C can be of any width 300px and 200px are just examples.
I've tried but unable to place it correctly.
For C i used flex: 1 1 0%; with A and C with fixed width - But didn't worked
You can give childB, You can read more about flex here
flex: 1;
.parent {
display: flex;
}
.child {
height: 300px;
display: flex;
justify-content: center;
align-items: center;
}
.childA {
flex-basis: 300px;
background-color: turquoise;
}
.childB {
flex: 1;
background-color: wheat;
}
.childC {
flex-basis: 200px;
background-color: blueviolet;
}
<div class="parent">
<div class="child childA">A</div>
<div class="child childB">B</div>
<div class="child childC">C</div>
</div>
it will be easier if you write your own code, which does not work
.abc {
display: flex;
height: 200px;
width: 400px;
margin: 0 auto;
border: 1px solid black;
}
.A {
min-width: 150px;
flex-shrink: 0;
background-color: aliceblue;
}
.B {
flex-grow: 1;
background-color: grey;
}
.C {
min-width: 100px;
flex-shrink: 0;
background-color: antiquewhite;
}
<div class="abc">
<div class="A"></div>
<div class="B"></div>
<div class="C"></div>
</div>
HTML :
<div class="container">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
</div>
CSS :
.container {
display: flex;
flex-wrap: nowrap;
border: 1px solid red;
height: 100px;
}
.box {
border: 1px solid black;
margin: 5px 5px 5px 5px;
}
.box:nth-child(2) {
width:25%;
background-color: blue;
}
you can use nth-child(child) to select any child and costom it
Result : https://codepen.io/pk-salma/pen/qBjqwBG
.main {
height: 100px;
width: 100px;
border: 1px solid;
background: green;
}
.columns {
display: flex;
}
.columns.vertical {
flex-direction: column;
flex-wrap: nowrap;
}
.box22 {
overflow: auto;
}
.box1 {
background: red;
}
.box2 {
background: orange;
border: 1px blue solid;
}
.box222 {
background: white;
border: 1px blue solid;
}
<md-content class="md-padding">
<div class="main columns vertical">
<nav class="box1">nav</nav>
<div class="box columns vertical">
<div class="b">asdasd</div>
<div class="box2 columns vertical">
<div class="box21 columns">
box21
</div>
<div class="box22 columns">
<div class="box221">box221</div>
<div class="box222">
<p>a</p>
<p>a</p>
</div>
</div>
</div>
</div>
</div>
</md-content>
I manually set the height of outermost box main and also set box22 with overflow:auto, however the box22 stretched out the main box and no scroll bar shows up.
What I want is to set height in the outermost box and the nested inner box can automitically control it's height thus all boxes are fitted. How to fix these kind of problem, should I set heights for all descendant boxes?
I tested setting overflow :auto at box(level1), box2(level2) and box22(level3), only box(level1) can automatically control it's height and shows up a scroll bar when it's height overlayed.
what I want is shown below, however, to achieve this, I need to manually specify the father box of box22. In other words, if I want to make a flex contaner scrollable, I have to at least set it's father box's height, which is toally unaccptable.
.main {
height: 100px;
width: 100px;
border: 1px solid;
background: green;
}
.columns {
display: flex;
}
.columns.vertical {
flex-direction: column;
flex-wrap: nowrap;
}
.box22 {
overflow: auto;
}
.box1 {
background: red;
}
.box2 {
height:64px;
background: orange;
border: 1px blue solid;
}
.box21 {
background: yellow;
}
.box222 {
background: white;
border: 1px blue solid;
margin-top: auto;
}
<md-content class="md-padding">
<div class="main columns vertical">
<nav class="box1">nav</nav>
<div class="box columns vertical">
<div class="b">asdasd</div>
<div class="box2 columns vertical">
<div class="box21 columns">
box21
</div>
<div class="box22 columns">
<div class="box221">box221</div>
<div class="box222">
<p>a</p>
<p>a</p>
<p>a</p>
</div>
</div>
</div>
</div>
</div>
</md-content>
Well, as you noted, the parent container needs a height declaration in order to generate a scrollbar.
This makes sense because there's no way to trigger an overflow condition if there's no fixed length.
With a flexible length (e.g., height: auto), the container will shrink and expand to accommodate content, never triggering an overflow and, therefore, never generating a scrollbar.
MDN describes it like this:
In order for overflow to have an effect, the block-level container must have either a set height (height or max-height) or white-space set to nowrap.
So that's your obstacle. Here's how you get around it (knowing that you can't set more heights):
Give the browser what it needs to trigger the overflow: set a tiny (1px) height.
You get the full height that you want: use flex-grow to consume remaining space.
So something like this...
height: 1px;
flex-grow: 1;
but more efficiently:
flex: 1 0 1px; /* fg, fs, fb */
Add this to your code:
.main .columns.vertical {
flex: 1 0 1px;
}
.box22 {
flex: 1 0 1px;
}
.main {
height: 100px;
width: 100px;
border: 1px solid;
background: green;
}
/* NEW */
.main .columns.vertical {
flex: 1 0 1px;
}
/* ADJUSTMENT */
.box22 {
flex: 1 0 1px;
overflow: auto;
}
.columns {
display: flex;
}
.columns.vertical {
flex-direction: column;
flex-wrap: nowrap;
}
.box22 {
flex: 1 0 1px;
overflow: auto;
}
.box1 {
background: red;
}
.box2 {
background: orange;
border: 1px blue solid;
}
.box222 {
background: white;
border: 1px blue solid;
}
<md-content class="md-padding">
<div class="main columns vertical">
<nav class="box1">nav</nav>
<div class="box columns vertical">
<div class="b">asdasd</div>
<div class="box2 columns vertical">
<div class="box21 columns">box21</div>
<div class="box22 columns">
<div class="box221">box221</div>
<div class="box222">
<p>a</p>
<p>a</p>
</div>
</div>
</div>
</div>
</div>
</md-content>
consider using max-height instead of height on main also... if you start with flexbox... best to keep display: flex through the whole chain
.top {
position: static;
height: 200px;
width: 200px;
max-height: 200px;
max-width: 200px;
overflow: auto;
}
.flexcol {
width: 100%;
display: flex;
flex-direction: column;
padding: 0;
}
.mynav {
display: flex;
flex-direction: row;
flex-grow: 1;
background-color: blue;
}
.box1 {
display: flex;
flex-grow: 1;
background-color: red;
}
.box2 {
display: flex;
flex-direction: column;
flex-grow: 1;
background-color: green;
}
.box3 {
display: flex;
flex-grow: 1;
background-color: yellow;
}
.box221 {
min-height: 50px;
background-color: pink;
width: 100%;
}
.box222 {
min-height: 50px;
background-color: grey;
width: 100%;
}
.darklink {
color: white;
}
<div class="top">
<div class="flexcol">
<nav class="mynav">
<a class="darklink" href="#" target="_">Link1</a>
<a class="darklink" href="#" target="_">Link2</a>
<a class="darklink" href="#" target="_">Link3</a>
</nav>
<div class="box1">
<p>para</p>
</div>
<div class="box2">
<div class="box221">
<p>para</p>
<p>para</p>
</div>
<div class="box222">
<p>para</p>
<p>para</p>
<p>para</p>
</div>
</div>
<div class="box3">
<p>para</p>
</div>
</div>
</div>
I want to align two images and a DIV. The DIV thats a rounded box keeps ending up beneath the two images.
Here's my HTML/CSS:
.main {
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 600px;
height: 110px;
}
.one {
float: right;
height: 100px;
}
.two {
height: 100px;
}
.box {
position: absolute;
height: 50px;
width: 50px;
}
.rounded {
border-radius: 10px;
border-color: #FFF;
border: 5px solid white;
}
<div id="main" class="main">
<div id="one" class="one">
</div>
<div id="two" class="two"><img src="[![apple][1]][1]" width="100" height="76" /> <img src="[![titleofpage][1]][1]" width="309" height="61" />
<div class="box rounded"></div>
</div>
</div>
How can I align them all in a straight line in this centered DIV in the middle of the page?
You can try out flexbox:
.flex-container-center {
display: flex;
align-items: center; /* this is what you need :) */
justify-content: center;
}
<div class="flex-container-center">
<img src="https://via.placeholder.com/200x200" />
<img src="https://via.placeholder.com/100x100" />
<img src="https://via.placeholder.com/200x50" />
</div>
Also, here's a working example and my favorite guide on flexbox :)
Add display: flex and justify-content: center to .two class;
.two {
display: flex;
justify-content: center;
height: 100px;
}
When using display: flex, there is a main-axis and cross-axis and you can set the main axis with flex-direction: row or flex-direction: column. The default is flex-direction: row without calling it. This means in the above example the main-axis = row and cross-axis = column.
When centering items using flex box you have two options:
align-items: center
justify-content: center
align-items controls the cross axis and justify-content controls the main axis.
In your example the main axis is row because the flex-direction wasn't called, so it used the default row. To center the items on the horizontal axis, you have to use justify-content, which uses the main axis (flex-direction) --> row
I tweaked the CSS to use grid view, removed the absolute positions and floats. Added borders so I could see things :)
.main{
position: block;
margin: 0 auto;
width: 600px;
height: 110px;
}
.one {
border: 5px solid blue;
height: 100px;
}
.two {
display: grid;
grid-template-columns: repeat(3, 30%);
height: 100px;
border: 5px solid yellow;
}
.box {
height:50px;
width:50px;
}
.rounded {
border-radius: 10px;
border-color:#FFF;
border: 5px solid red;
}