Here's the fiddle:
body {
background-color: #D3D3D3;
}
#container {
display: flex;
flex-direction: column;
width: 100%;
gap: 10px;
padding: 20px;
}
.section1 {
display: flex;
justify-content: center;
}
.section2 {
display: flex;
justify-content: center;
gap: 10px;
}
.column {
display: flex;
flex-direction: column;
gap: 10px;
}
.show {
padding: 20px;
border: 2px black solid;
width: 100%;
}
.section3 {
display: flex;
justify-content: center;
}
<div id="container">
<div class="section1">
<div class="header show"> header </div>
</div>
<div class="section2">
<div class="column">
<div class="content1 show"> content 1</div>
<div class="content2 show"> content 2</div>
</div>
<div class="content3 show"> content 3</div>
</div>
<div class="section3">
<div class="footer show"> footer</div>
</div>
</div>
I tried using overflow: auto;, overflow: hidden;, and z-index: 1; but all of those didn't work. I this has something to do with the width: 100%; in the .show divs. I tried using width: 60%; instead and that stops it from overlapping but it doesn't occupy all the width. What should I do to stop the .show divs from overlapping while maintaining all the width?
If you use box-sizing: border-box that will solve your issues: the reason being that when you have padding: 20px; width: 100%, it actually adds 40px to the already 100% width, unless you explicitly set this box-sizing property.
* {
box-sizing: border-box;
}
This will fix your layout issues: see proof-of-concept fix of your fiddle. This is also why it's recommended to use a CSS reset.
p/s: Consider using CSS grid for your layout, it's way easier to reason about.
Add * {box-sizing: border-box;} to your code.
More about Box sizing
https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing
Your immediate problem has been solved - as others have suggested you can set box-sizing so the padding is included in the dimensions.
However, your HTML is quite complex because of using flex. Your desired layout looks more like a grid - grid being suited to 2D type layouts.
This snippet simplifies your HTML - each of the elements is at the same 'level' the need for separate sections being removed.
The grid-template-areas CSS property is used to layout the contents.
* {
box-sizing: border-box;
}
body {
background-color: #D3D3D3;
}
#container {
display: grid;
grid-template-columns: 1fr 9fr;
grid-template-areas: 'H H' 'C1 C3' 'C2 C3' 'F F';
width: 100%;
gap: 10px;
padding: 20px;
}
.show {
padding: 20px;
border: 2px black solid;
width: 100%;
}
.header {
grid-area: H;
}
.content1 {
grid-area: C1;
}
.content2 {
grid-area: C2;
}
.content3 {
grid-area: C3;
}
.footer {
grid-area: F;
}
<div id="container">
<div class="header show"> header </div>
<div class="content1 show"> content 1</div>
<div class="content2 show"> content 2</div>
<div class="content3 show"> content 3</div>
<div class="footer show"> footer</div>
</div>
Related
I am trying to render rows with the date on the left and some text on the right.
I cant seem to work out how I changed the widths of the columns though?
Currently my day and text column are the same width.
I'd like to have the day as 50px and the text as 300px.
Is it possible with this code?
.sb-flex-row {
flex-direction: row;
display: flex;
}
.sb-flex-column {
flex-direction: column;
display: flex;
}
.sb-flex-body {
display: flex;
}
.sb-flex-body div:not([class*="flex"]) {
border: 1px solid white;
flex: 1 1 50px;
width: 200px;
}
<div class="sb-flex-body">
<div class="sb-flex-row">
<div style="background: #0980cc;">day</div>
</div>
<div class="sb-flex-column">
<div style="background: #09cc69;">month</div>
<div style="background: #cc092f;">year</div>
</div>
<div class="sb-flex-row">
<div style="background: #0980cc;">text</div>
</div>
</div>
I cleaned up and make it maybe simpler for you to understand. You have an outer wrapper that is flexible. The default direction is row and that is ok. Then you have two blocks. one block dateBlock and the second is a text block. the dateblock contains two blocks (a,b). and b you can assign the direction to the column. Afterward, you can assign the width to the text block and Dateblock. That is it :-)
.wrapper {
display: flex;
gap:10px;
}
.dateBlock {
display: flex;
background: yellow;
gap: 20px;
padding: 10px;
box-sizing: border-box;
}
.textBlock {
background: green;
padding: 10px;
box-sizing: border-box;
width: 300px;
}
.monthYear {
display: flex;
flex-direction: column;
width:50px;
}
.day {
font-size: 30px;
width: 50px;
}
<div class="wrapper">
<div class="dateBlock">
<div class="day">day</div>
<div class="monthYear">
<div>month</div>
<div>year</div>
</div>
</div>
<div class="textBlock">text</div>
</div>
I rearranged your markup a bit to easily target these divs in the style sheet. You can see the changes I made to your CSS under /* changes */. Also, take note of the HTML I adjusted.
.sb-flex-row {
flex-direction: row;
display: flex;
}
.sb-flex-column {
flex-direction: column;
display: flex;
}
.sb-flex-body {
display: flex;
}
/* changes */
.sb-flex-body div:not([class*="flex"]) {
border: 1px solid white;
width: 50px;
}
.sb-flex-row > div {
min-width: 300px;
}
<div class="sb-flex-body">
<div class="sb-flex-column">
<div style="background: #0980cc;">day</div>
<div style="background: #09cc69;">month</div>
<div style="background: #cc092f;">year</div>
</div>
<div class="sb-flex-row">
<div style="background: #0980cc;">text</div>
</div>
</div>
My question is: How can I put a margin between the 2 elements, without misaligning them in smaller screens?
I'm creating an HTML page with 2 elements disposed along a line, like this:
I made it responsive, so when I have a smaller screen, the elements are wrapped to another line:
Here's a fiddle to this: https://jsfiddle.net/5ye2sc4b/1/
Html:
<div class="container">
<div class="header">Header</div>
<div class="line">
<div class="element element1">Element 1</div>
<div class="element element2">Element 2</div>
</div>
<div class="footer">Footer</div>
</div>
CSS:
.container {
display:flex;
flex-direction: column;
margin-top: 10px;
}
.header, .footer {
background-color: lightblue;
padding: 5px;
margin-bottom: 5px;
margin-top: 5px;
}
.line {
display: flex;
flex-direction: row;
flex-wrap: wrap;
}
.element {
border: 1px solid gray;
flex-grow: 1;
height: 100px;
}
If I put a right margin in element 1, it will be displayed correctly in bigger screens:
element1 { margin-right: 20px; }
But it will be misaligned to the header on smaller screens:
On the fiddler above I put some buttons to change the global container size, to simulate the problem.
While i think your approach is not the best way to create a responsive layout you might want to simply remove the margin on smaller screens:
#media (max-width: 620px) {
margin-right: 0px
}
I think this is more suitable for CSS grid where you can use gaps:
.container {
/*display: flex;
flex-direction: column; not really useful in this case*/
margin-top: 10px;
}
.header,
.footer {
background-color: lightblue;
padding: 5px;
margin-bottom: 5px;
margin-top: 5px;
}
.line {
display: grid;
/* adjust the 200px to control when elements will wrap */
grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
/* margin only between columns */
grid-column-gap:16px;
}
.element {
border: 1px solid gray;
height: 100px;
}
<div class="container">
<div class="header">Header</div>
<div class="line">
<div class="element element1">Element 1</div>
<div class="element element2">Element 2</div>
</div>
<div class="footer">Footer</div>
</div>
You could do this using media queries:
Make sure your .line has flex-flow: row nowrap; the shorthand code for flex-direction: row;
flex-wrap: nowrap; initially. The children should have a flex-basis of 50%
Then let the media query (#media) do the rest.
As soon as your screen goes below 900px, apply the CSS inside the media query like so:
#media(max-width: 900px){
.line{
flex-flow: row wrap;
}
.element{
flex-basis: 100%;
}
.element1 {
margin-right: 0px;
}
this will remove the margin from your element1 aswell as set the elements to 100% flex basis, aswell as the flex wrap on the .line for it to wrap.
.container {
display:flex;
flex-direction: column;
margin-top: 10px;
}
.header, .footer {
background-color: lightblue;
padding: 5px;
margin-bottom: 5px;
margin-top: 5px;
}
.line {
display: flex;
flex-flow: row nowrap;
}
.element {
border: 1px solid gray;
flex-grow: 1;
height: 100px;
flex-basis: 50%;
}
.element1 { margin-right: 20px; }
#media(max-width: 900px){
.line{
flex-flow: row wrap;
}
.element{
flex-basis: 100%;
}
.element1 {
margin-right: 0px;
}
Html:
<div class="container">
<div class="header">Header</div>
<div class="line">
<div class="element element1">Element 1</div>
<div class="element element2">Element 2</div>
</div>
<div class="footer">Footer</div>
</div>
I'm trying to create a sidebar that is a fixed percentage of the view port. Inside the sidebar, I'd like an element that is fixed to the top while the rest of content scrolls if it take up more vertical space than the sidebar height.
In this example, the h1 element remains at the top of the parent element while the rest of the content, .inner can be scrolled. The content and scroll bar inside .inner is cut off by the height of the h1 element.
How can I display the all the content and scroll bar?
* { box-sizing: border-box; margin: 0; padding: 0; }
body: {
height: 100vh;
}
.grid-container {
display: grid;
grid-template-columns: 1fr 5fr;
grid-template-areas: 'left right';
justify-content: space-around;
grid-gap: 12px;
width: 90vw;
height: 100vh;
margin: auto;
}
.left {
grid-area: left;
}
.right {
gird-area: right
}
.side {
display: flex;
flex-direction: column;
justify-content: center;
height: 100%;
}
.outer {
height: 90vh;
margin: auto;
position: relative;
border: 1px solid blue;
overflow:hidden;
}
.inner {
height: 100%;
overflow: auto;
}
h1 {
height: 100px;
background: lightgrey;
}
p {
height: 100px;
}
<div class="grid-container">
<div class="left">
<div class="side">
<div class="outer">
<h1>other content</h1>
<div class="inner">
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
</div>
</div>
</div>
</div>
<div class="right"></div>
</div>
You want to avoid setting explicit heights on things whenever possible. That tends to bite you. Set the rules for your flex layout and let it do its thing. If you need whitespace somewhere, keep things simple and add it to the box's contents, not the box itself. By separating the concerns of layout and content, you make it easier to pluck out one bit of content and replace it without getting into the CSS for your layout.
Scroll into the CSS for hints.
* { box-sizing: border-box; margin: 0; padding: 0; }
body: {
height: 100vh;
}
.grid-container {
display: grid;
grid-template-columns: 1fr 5fr;
grid-template-areas: 'left right';
justify-content: space-around;
grid-gap: 12px;
width: 90vw;
height: 100vh;
margin: auto;
}
.left {
grid-area: left;
}
.right {
gird-area: right
}
.side {
display: flex;
flex-direction: column;
justify-content: center;
height: 100%;
}
.outer {
height: 90vh;
margin: auto;
position: relative;
border: 1px solid blue;
display: flex; /* <--------------- change */
flex-direction: column; /* <--------------- add */
}
.inner {
/* height: 100%; <--------------- remove */
overflow: auto;
}
h1 {
flex: 0 0; /* <--------------- change */
background: lightgrey;
}
p {
height: 100px;
}
<div class="grid-container">
<div class="left">
<div class="side">
<div class="outer">
<h1>other content</h1>
<div class="inner">
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<p>5</p>
</div>
</div>
</div>
</div>
<div class="right"></div>
</div>
I need to have different layouts for a dashboard. I need only horizontal scroll for layout-container if the items exceed to fit in a visible viewport. I came across a layout with the following requirements.
I have created the layout style using CSS-flexbox, but could not get the horizontal scroll, got the vertical scroll only.
html,
body {
height: 100%;
margin: 0px;
}
* {
box-sizing: border-box;
}
.flexbox {
height: 100%;
width: 100%;
display: flex;
flex-wrap: wrap;
overflow-x: auto;
background-color: lightgreen;
}
.item {
min-width: 50%;
min-height: 50%;
flex: 1 0 0;
border: 1px solid;
}
.item:nth-child(odd) {
background-color: lightblue;
}
.item:nth-child(even) {
background-color: lightslategray;
}
.item1 {
min-width: 100%;
}
<div class="flexbox">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item1">4</div>
<div class="item item2">5</div>
<div class="item item3">6</div>
</div>
https://codepen.io/TechnoGeek/pen/GdZodo
So, I thought, CSS grid can help with this. So I tried something but did not understand how to get it.
html,
body {
height: 100%;
margin: 0px;
}
.grid {
display: grid;
height: 100%;
background-color: lightgreen;
grid-template-columns: repeat(2, 1fr);
grid-template-row: repeat(2, 1fr);
grid-gap: 5px;
/* grid-auto-flow: column; */
}
.item {
border: 1px solid;
}
.item:nth-child(odd) {
background-color: lightblue;
}
.item:nth-child(even) {
background-color: lightslategray;
}
.item1 {
grid-column: 1/3;
}
<div class="grid">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item1">4</div>
<div class="item item2">5</div>
<div class="item item3">6</div>
</div>
https://codepen.io/TechnoGeek/pen/BxKoaG
In the grid layout, items are shrinking to fit within the layout.
The number of items inside the container is dynamic. Irrespective of the item count the layout must maintain the structure for each visible group.
Can someone help how to achieve this?
Thanks in advance.
I found a satisfactory answer using CSS Grid layout.
In the grid layout, items are shrinking to fit within the layout.
I have defined the grid lines using fr in my question that is why the items are shrinking. Now I have used % because I want the cell items to flow out of visible area to produce scroll if needed.
and span keyword in defining grid cell areas helped a lot for auto placement of grid cells.
From MDN: span && [ <integer> || <custom-ident> ]
Contributes a grid span to the grid item’s placement such that the corresponding edge of the grid item’s grid area is n lines from the opposite edge.
html,
body {
height: 100%;
margin: 0px;
}
.grid {
display: grid;
height: 100%;
background-color: lightgreen;
grid-template-columns: repeat(2, 50%);
grid-template-rows: repeat(2, 50%);
/*grid-gap: 5px;*/
grid-auto-columns: 50%;
grid-auto-flow: column;
}
.item {
border: 1px solid;
grid-area: span 1 / span 1;
}
.item:nth-child(odd) {
background-color: lightblue;
}
.item:nth-child(even) {
background-color: lightslategray;
}
.item1 {
grid-area: span 1/ span 2;
}
<div class="grid">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
<div class="item item1">4</div>
<div class="item item2">5</div>
<div class="item item3">6</div>
</div>
For horizontal scroll the simplest solution would be to create a separate container for each view. Then make the overall container (body) a flex container in row direction.
body {
display: flex;
margin: 0;
}
.flexbox {
flex: 0 0 100vw;
height: 100vh;
display: flex;
flex-wrap: wrap;
background-color: lightgreen;
}
.item {
flex: 1 0 50%;
min-height: 50%;
border: 1px solid;
}
.item1 {
flex-basis: 100%;
}
.item:nth-child(odd) {
background-color: lightblue;
}
.item:nth-child(even) {
background-color: lightslategray;
}
* {
box-sizing: border-box;
}
<div class="flexbox">
<div class="item item1">1</div>
<div class="item item2">2</div>
<div class="item item3">3</div>
</div>
<div class="flexbox">
<div class="item item1">4</div>
<div class="item item2">5</div>
<div class="item item3">6</div>
</div>
The main trick is to add grid-auto-flow: column; to your container's display grid css styles.
For Example
.container-grid {
display: grid;
grid-gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(20rem, 20rem));
grid-auto-flow: column;
overflow-x: auto;
}
try to add class with this style to the element that you want to have horizontal scroll on it
display: block;
width: 99%;
overflow-x: auto;
I'm trying to create a simple header and I'm having problems with the logo image because it's taking more space than needed.
.wrapper {
display: flex;
flex-direction: row;
height: 50px;
}
.logo {
padding: 5px;
}
img {
height: 100%;
}
.content {
padding: 5px;
}
<div class="wrapper">
<div class="logo"><img src="http://placehold.it/350x150"/></div>
<div class="content">content</div>
</div>
As you can see, the "content" text isn't placed near the logo, because the logo wrapper has a width equal to the size of the image before it gets resized by CSS.
I noticed that if I set height: 100% to the .logo element the situation is a bit better, but doing so, the "content" text overlaps a bit the image.
How can I fix it?
Here are two ways to fix the problem:
Method #1 – Remove the extra wrapper. Make the image itself the flex item.
.wrapper {
display: flex;
flex-direction: row;
height: 50px;
}
img {
height: 100%;
}
.content {
padding: 5px;
}
<div class="wrapper">
<img src="http://placehold.it/350x150"/><!-- div wrapper removed -->
<div class="content">content</div>
</div>
Method #2 – Define a height for the image wrapper. (No changes to the HTML.)
.wrapper {
display: flex;
flex-direction: row;
height: 50px;
}
.logo {
height: 100%; /* new */
border: 1px dashed red;
}
img {
height: 100%;
}
.content {
padding: 5px;
margin-left: 5px;
border: 1px dashed red;
}
<div class="wrapper">
<div class="logo"><img src="http://placehold.it/350x150" /></div>
<div class="content">content</div>
</div>
You have to explicitly set image height in pixels. height: 100% will use the image original height, NOT its container height.
I added justify-content and align-items to the flex container so things get properly positioned.
.wrapper {
display: flex;
flex-direction: row;
height: 50px;
justify-content: flex-start;
align-items: flex-start;
}
.logo {
padding: 5px;
}
img {
max-height: 50px
}
.content {
padding: 5px;
}
<div class="wrapper">
<div class="logo"><img src="http://placehold.it/350x150"/></div>
<div class="content">content</div>
</div>