I'm trying to replicate the main layout of Spotify, however, I have two problems, which are:
I am not able to place the two containers(Blue and Red) to be the
ideal height.
I am not able to put the Container(Yellow) to be at the bottom.
.main {
height: 100vh;
width: 100vw;
display: flex;
flex-wrap: wrap;
background-color: black;
}
.blue {
background-color: blue;
}
.red {
flex: 1;
display: flex;
background-color: red;
}
.yellow {
height: 91px;
flex: 1 0 100%;
display: flex;
flex-direction: column;
justify-content: flex-end;
background-color: yellow;
}
<div class="main">
<div class="blue">blue</div>
<div class="red">red</div>
<div class="yellow">yellow</div>
</div>
Related
I have a flex-box layout where I'm using flex-grow: 1 on multiple elements in order to distribute the layout evenly. However, when I add contents to one of the elements, it immediately expands out and ruins the even layout.
How can I make it so that the parents stay evenly distributed? Or would it be easier to just change it to width: 50% in order to fix that problem? Below is the code.
.app-container {
display: flex;
background: orange;
min-height: 100vh;
min-width: 100vw;
}
.sideBar-container {
display: flex;
background: pink;
width: 10%;
}
.info-container {
display: flex;
flex-direction: column;
flex-grow: 1;
height: 100vh;
}
.top-container {
display: flex;
background: green;
flex-grow: 1;
}
.bottom-container {
flex-grow: 1;
display: flex;
background: wheat;
}
.top-left {
display: flex;
flex-direction: column;
background: blue;
flex-grow: 1;
}
.top-right {
display: flex;
background: red;
flex-grow: 1;
}
.top-two {
display: flex;
justify-content: space-around;
align-items: center;
flex-grow: 1;
background: gold;
}
.bottom-two {
display: flex;
justify-content: space-around;
align-items: center;
flex-grow: 1;
background: cornflowerblue;
}
.number-appts {
background: aqua;
flex-basis: 35%;
height: 45%;
}
.projected-revenue {
background: aquamarine;
flex-basis: 45%;
}
.projected-costs {
background: burlywood;
}
.projected-profit {
background: darkgray;
}
.appointment-consult {
background: seagreen;
}
<div className="app-container">
<div className="sideBar-container">
</div>
<div className="info-container">
<div className="top-container">
<div className="top-left">
<div className="top-two">
<div className="number-appts">test</div>
<div className="projected-revenue">this</div>
</div>
<div className="bottom-two">
<div className="projected-costs">here</div>
<div className="projected-profit">testing</div>
</div>
</div>
<div className="top-right">
<div className="appointment-consult"></div>
</div>
</div>
<div className="bottom-container"></div>
</div>
</div>
I figured it out. Changed my flex-grow: 1 to flex:1 as creating a rule where flex-basis is now 0px rather than auto stops the css from looking inward at the content
I am trying to style a div that has two children, with flexbox and flex-wrap, without media-queries, that at a certain width is space-between, but once it is a single column is centered (as opposed to currently where once it wraps it's like flex-start). Hopefully that makes sense.
I think this is the relevant code, basically when it wraps, i would like space between to become center:
HTML and CSS
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
I hope this fits your needs.
Since I don't believe that there is a way to solve your problem using only native CSS (i.e. no media queries, and I assume no JS), I let myself change the space-between to space-around (since you gave .content 82% there is not much of a difference).
if you do not want to use space-around, I find it hard for me to believe that there is a solution without media-queries \ JS.
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
place-items: center;
justify-content: space-around;
width: 100%;
}
h1 {
width: min-content;
}
h6 {
width: min-content;
}
<div class="content-container">
<div class="content">
<h1 class="content__1">'content1'</h1>
<h6 class="content__2">'content2'</h6>
</div>
</div>
Do you want like this:
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: center;
text-align: center;
width: 82%;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
I'm afraid it's impossible to achieve what you want the way you want (i.e., CSS without a #media query).
Solution 1: CSS without a #media query
If you don’t want to use a #media query, then look at Solution 1. But space-around is a different thing than space-between because space-between will push your two elements all the way to the left and right when they’re not stacked above each other, while space-around will not do so.
An example of space-between:
An example of space-around:
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
If Solution 1 is good enough for you, then you don’t need to read further. But there are many better options on the table. If you’re not limited and can make changes to your code, then I think you should look at other possible solutions below. You can use different approaches to achieve what you want if you want your two elements to be pushed all the way to the left and right when they’re not stacked above each other.
The reason why this can’t be done without using a #media query, JavaScript or jQuery is that CSS on its own can’t “switch” from space-between to space-around when your two elements get stacked above each other. You need to define some rules using a #media query, JavaScript or jQuery so that CSS will change from space-between to space-around at a specific window width (i.e., exactly when your two elements get stacked above each other). See other possible solutions below.
Solution 2: CSS with a #media query
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
#media only screen and (max-width: 708px) {
.content {
justify-content: space-around;
}
}
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
Solution 3: JavaScript
window.onload = function() {
if (window.innerWidth < 709) {
document.getElementById("content").style.justifyContent = "space-around";
} else {
document.getElementById("content").style.justifyContent = "space-between";
}
}
window.onresize = function() {
if (window.innerWidth < 709) {
document.getElementById("content").style.justifyContent = "space-around";
} else {
document.getElementById("content").style.justifyContent = "space-between";
}
}
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<div class="content-container">
<div class="content" id="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
Solution 4: jQuery
$(window).on('load', function() {
if ($(window).width() < 709) {
$(".content").css("justify-content", "space-around");
} else {
$(".content").css("justify-content", "space-between");
}
});
$(window).on('resize', function() {
if ($(window).width() < 709) {
$(".content").css("justify-content", "space-around");
} else {
$(".content").css("justify-content", "space-between");
}
});
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
width: 82%;
text-align: center;
line-height: 50px;
border: 2px solid red;
}
.content h1 {
min-width: 20rem;
background-color: #DCDCDC;
}
.content h6 {
min-width: 15.5rem;
background-color: #DCDCDC;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<div class="content-container">
<div class="content">
<h1>Content 1</h1>
<h6>Content 2</h6>
</div>
</div>
P.S. I added text-align: center; and line-height: 50px; to the .content class because if you really want to have your content centered then you also need to center text horizontally and vertically inside your containers. This is a quick fix, you can remove that if you want. Also, border: 2px solid red; is added to the .content class so you can better understand the difference between space-between and space-around.
Try this.
.content-container {
display: flex;
justify-content: center;
width: 100%;
text-align:center;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
width: 82%;
text-align:center;
}
.content h1 {
min-width: 20rem;
}
.content h6 {
min-width: 15.5rem;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
Here is an idea using clamp() where I will toggle between a fixed width and full width based on a parameter (50rem in this case)
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
}
.content > * {
width: clamp(15rem, (50rem - 100vw)*9999, 100%);
outline: 1px solid red;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<h6>'content2'</h6>
</div>
</div>
Related article if you want more detail: https://css-tricks.com/responsive-layouts-fewer-media-queries/
The following solution uses only flexbox, no media queries or JavaScript. Does this do what you want?
.content-container {
display: flex;
justify-content: center;
width: 100%;
}
.content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
width: 82%;
text-align: center;
}
.content h1,
.content h6 {
flex: 1;
}
.horizontal-spacing {
flex: 1;
min-width: calc(20rem + 15.5rem);
height: 0;
}
<div class="content-container">
<div class="content">
<h1>'content1'</h1>
<span class="horizontal-spacing"></span>
<h6>'content2'</h6>
</div>
</div>
I cannot understand WHY I am not getting this:
.container {
width: 600px;
height: 400px;
border: 3px solid green;
}
.cg-panel {
display: flex;
flex-flow: column;
align-items: stretch;
justify-content: center;
}
.cg-panel .content {
flex: 1;
background-color: tomato;
}
<div class="container">
<div class="cg-panel">
<div class="content"></div>
</div>
</div>
I, for the life of me, cannot understand why the content panel does not vertically stretch the entire container. What is the purpose of "flex:1" if it isn't going to work? Am I not reading the documentation correctly?
There's nothing in your CSS that is expanding the height of .cg-panel to fit its parent .container.
Adding height: 100%; to .cg-panel fixes this:
.container {
width: 600px;
height: 400px;
border: 3px solid green;
}
.cg-panel {
display: flex;
flex-flow: column;
align-items: stretch;
justify-content: center;
height: 100%; /* add this */
}
.cg-panel .content {
flex: 1;
background-color: tomato;
}
<div class="container">
<div class="cg-panel">
<div class="content"></div>
</div>
</div>
How do I stretch the divs with a yellow background to full height? It should cover up the green but it is not working. I tried adding height: 100% on it but then it adds up the height from the search bar?
https://jsfiddle.net/nuy20j1h/
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-wrap: wrap;
align-items: flex-start;
width: 75%;
background: green;
}
.search-bar {
width: 100%;
padding: 25px;
background: blue;
}
.content-wrap {
display: flex;
flex-wrap: wrap;
width: 100%;
align-items: flex-stretch;
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
First you should add a style reset, I'm using this now * {} as you can se below. The trick here is to run flex-direction: column; on .home and you can tell .content-wrap to take up the rest of that space after the search with flex-grow: 1;
box-sizing: border-box; is, if you add let's say width: 200px; to a element, and add padding: 20px;, the element will stay 200px with the padding included. If you don't have that, it will take up 200px + 40px.
if you want the fiddle, here it is
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: flex-start;
width: 75%;
background: green;
}
.search-bar {
width: 100%;
padding: 25px;
background: blue;
}
.content-wrap {
display: flex;
flex-grow: 1;
flex-wrap: wrap;
width: 100%;
align-items: flex-stretch;
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
As mentioned in other answers, there is one main issue here:
flex-direction: column;, which I added to home, to enable the usage of flex properties instead of height, to make the .content-wrap fill the available space left in home
That will make the .search-bar and .content-wrap stack vertical, and enable the use of flex: 1 on .content-wrap, which will make it fill the remaining space/height.
So even if you got answers already, and since there are some properties with wrong value, or not needed, I decided to post an answer to clarify the changes made.
See my notes made in the CSS for further clarifications and what I changed.
Stack snippet
.block {
width: 80%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
}
.sidebar {
height: 600px;
width: 25%;
background: red;
}
.home {
display: flex;
flex-direction: column; /* added */
/*flex-wrap: wrap; removed, not needed */
/*align-items: flex-start; removed, items should fill parent's,
in this changed case, width */
width: 75%;
background: green;
}
.search-bar {
/*width: 100%; not needed, default for column
item is to fill parent width as
its "align-items" is "stretch" */
padding: 25px;
background: blue;
}
.content-wrap {
flex: 1; /* added, take the remaining space left
left of its parent (height in this case) */
display: flex;
flex-wrap: wrap;
/*width: 100%; not needed, default for column
item is to fill parent width as
its "align-items" is "stretch" */
/*align-items: flex-stretch; wrong value, should be "stretch",
though since that is the default,
it is not needed */
}
.content,
.single {
width: 50%;
background: yellow;
}
<div class="block">
<div class="sidebar">sidebar</div>
<div class="home">
<div class="search-bar">search bar</div>
<div class="content-wrap">
<div class="content">lorem ipsum</div>
<div class="single">test</div>
</div>
</div>
</div>
flex-direction: column; is your friend. Here is a reworked fiddle of your code: https://jsfiddle.net/vsjktmms/1/
Using the same HTML structure you provided:
.block {
display: flex;
width: 80%;
margin: 0 auto;
background-color: gray;
align-items: stretch;
}
.sidebar {
width: 25%;
height: 600px;
background-color: red;
}
.home {
display: flex;
flex-direction: column;
align-items: stretch;
width: 75%;
background-color: green;
}
.search-bar {
padding: 25px;
background-color: blue;
}
.content-wrap {
flex: 1 1 auto;
display: flex;
flex-wrap: wrap;
width: 100%;
background-color: pink;
}
.content,
.single {
width: 50%;
background: yellow;
}
I am a backend programmer by profession. But I have just started to learn flexbox and I want to hit the sky with flexbox.
So, I created a simplest design but which looks most complicated to me when creating it using flexbox.
Here is the design:
Guys, I am not able to figure out, how to use flexbox in such a case as there is no row or column. I don't know but is there anything like rowspan or colspan in flexbox that I can use to arrange these divs as shown in image above?
Here is my code:
HTML:
<div class="wrapper">
<div class="div-wrapper1">
<div class="inner-wrapper1">
<div class="div1"></div>
<div class="fake1"></div>
</div>
<div class="div2"></div>
</div>
<div class="div-wrapper2">
<div class="div3"></div>
<div class="inner-wrapper2">
<div class="fake2"></div>
<div class="div4"></div>
</div>
</div>
<div class="div-center"></div>
</div>
CSS:
.wrapper {
height: 200px;
width: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
}
.div-wrapper1 {
display: flex;
flex: 1;
}
.div-wrapper2 {
display: flex;
flex: 1
}
.inner-wrapper1 {
display: flex;
flex: 3;
flex-direction: column;
}
.div1 {
background-color: red;
display: flex;
flex: 3
}
.fake1 {
display: flex;
flex: 1
}
.div2 {
background-color: green;
display: flex;
flex: 2
}
.div3 {
background-color: blue;
display: flex;
flex: 2
}
.inner-wrapper2 {
display: flex;
flex: 3;
flex-direction: column;
}
.div4 {
background-color: yellow;
display: flex;
flex: 3
}
.fake2 {
display: flex;
flex: 1
}
.div-center {
background-color: black;
}
This is my output:
Here is the codepen
Maybe a solution is to simply add a negative margin to .div-wrapper1 and you will get the exact layout :
.wrapper {
height: 200px;
width: 200px;
border: 1px solid black;
display: flex;
flex-direction: column;
}
.div-wrapper1 {
display: flex;
flex: 1;
}
.div-wrapper2 {
display: flex;
flex: 1;
margin-top: -30px;
}
.div-wrapper3 {
display: flex;
flex: 1
}
.inner-wrapper1 {
display: flex;
flex: 3;
flex-direction: column;
}
.div1 {
background-color: red;
display: flex;
flex: 3
}
.fake1 {
display: flex;
flex: 1
}
.div2 {
background-color: green;
display: flex;
flex: 2
}
.div3 {
background-color: blue;
display: flex;
flex: 2
}
.inner-wrapper2 {
display: flex;
flex: 3;
flex-direction: column;
}
.div4 {
background-color: yellow;
display: flex;
flex: 3
}
.fake2 {
display: flex;
flex: 1
}
.div-center {
background-color: black;
}
<div class="wrapper">
<div class="div-wrapper1">
<div class="inner-wrapper1">
<div class="div1"></div>
<div class="fake1"></div>
</div>
<div class="div2"></div>
</div>
<div class="div-wrapper2">
<div class="div3"></div>
<div class="inner-wrapper2">
<div class="fake2"></div>
<div class="div4"></div>
</div>
</div>
<div class="div-center"></div>
</div>
And if you want here is another solution without any negative values and a content inside the white part (simply adjust height/width as you need) :
.first,
.second {
display: flex;
height: 100px;
width: 200px;
}
.first:before {
content: "";
background: red;
flex: 3;
}
.first:after {
content: "";
background: green;
flex: 2;
}
.second:before {
content: "";
background: blue;
flex: 2;
}
.second:after {
content: "";
background: yellow;
flex: 3;
}
.fake {
display: flex;
height: 20px;
width: 200px;
}
.fake a {
flex: 1;
text-align: center;
}
.fake:before {
content: "";
background: blue;
flex: 2;
}
.fake:after {
content: "";
background: green;
flex: 2;
}
<div class="first">
</div>
<div class="fake">
link
</div>
<div class="second">
</div>
Here is another solution by simply using multiple linear-gradient:
.box {
display: flex;
height: 220px;
width: 200px;
justify-content: center;
align-items: center;
background-image:linear-gradient(to right,red 66%,green 0%),
linear-gradient(to right,blue 33%,white 0%,white 66%,green 66%),
linear-gradient(to right,blue 33%,yellow 0%);
background-size:100% 100px,100% 20px,100% 100px;
background-position:top,center,bottom;
background-repeat:no-repeat;
}
<div class="box">
link
</div>