Elements going beneath div for position = fixed - css

When I give position = fixed, elements on the right side is going beneath the black menu bar shown on the left side.
What is the way to make sure the yellow container starts only from the point the black container ends?
.menubar {
background: black;
height: 100vh;
overflow: none;
position: fixed;
}
.grid--1x2{
grid-template-columns: 1fr 1fr;
}
.grid {
display: grid;
}
.overflow {
overflow:auto;
}
.rightside
{
background:yellow;
margin-bottom:"100px"
}
<div className='grid grid--1x2 grid--3070'>
<div class="menubar">This is left side menu bar</div>
<div >
<div class='overflow'>
<h1 class="rightside" >hello world</h1>
<h1 class="rightside" >hello world</h1>
<h1 class="rightside" >hello world</h1>
</div>
</div>
</div>

position: fixed on your menu bar will remove it from the document flow. This means that your fixed elements will float on top of everything else.
One way to solve the issue would be to give your overflow class a margin-left that is the same width as your menubar.
.menubar {
background: black;
height: 100vh;
overflow: none;
position: fixed;
}
.grid--1x2{
grid-template-columns: 1fr 1fr;
}
.grid {
display: grid;
}
.overflow {
overflow:auto;
margin-left: 170px;
}
.rightside
{
background:yellow;
margin-bottom:"100px"
}
<div className='grid grid--1x2 grid--3070'>
<div class="menubar">This is left side menu bar</div>
<div >
<div class='overflow'>
<h1 class="rightside" >hello world</h1>
<h1 class="rightside" >hello world</h1>
<h1 class="rightside" >hello world</h1>
</div>
</div>
</div>

Related

flex-column: how to limit the height of grow part so it does not expand?

I'm sure this kind of question was asked before, but I really can't describe it exactly and concisely enough to let the search engine to understand me. So here we go:
To better explain my question I'm writing the code in tailwind style here. A stack snippet is also attached below:
<div class="root w-screen h-screen flex flex-col">
<div class="header h-[72px] w-full bg-red shrink-0"></div>
<div class="content grow">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
</div>
In this example, I would like to limit the height of the entire div.root to 100vh. However, because div.content is very tall, it expands the body that it shows a vertical scrollbar.
Well this is fairly easy to overcome, I only need to add scroll-y-auto to div.content. So the body scrollbar disappears, and div.content shows a vertical scrollbar. Perfect.
However later on, I decided to split div.content into two columns: both column shall have its own vertical scrollbar. Intuitively I changed the code to:
<div class="root w-screen h-screen flex flex-col">
<div class="header h-[72px] w-full bg-red shrink-0"></div>
<div class="content grow">
<div class="left overflow-y-auto">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
<div class="right overflow-y-auto">
<!-- a whole lot of content, very tall, height > 2000 px -->
</div>
</div>
</div>
But this does not work at all, as the attached snippet demonstrates. body got its scrollbar back, but not div.left or div.right.
I've explored several ways to solve this problem. In the end the best solution I got was to set the height of div.content to calc(100% - 72px). This works perfectly, but I understand it's only because I know the exact height of div.header is fixed at 72px.
Was I doing something wrong here? What's the most elegant way to solve this kind of problem?
body {
margin: 0;
}
.root {
width: 100vw;
height: 100vh;
display: flex;
flex-direction: column;
}
.header {
height: 72px;
width: 100%;
background-color: red;
flex-shrink: 0;
}
.content {
flex-grow: 1;
display: flex;
flex-direction: row;
}
.very-tall-content {
background-color: green;
height: 2400px
}
.left, .right {
flex-grow: 1;
margin: 0 4px;
overflow-y: auto;
}
<div class="root">
<div class="header"></div>
<div class="content">
<div class="left">
<p class="very-tall-content"></p>
</div>
<div class="right">
<p class="very-tall-content"></p>
</div>
</div>
</div>
Allright, try this one maybe it fixed your problem :)
instead of using flex for .root use grid. down here we have a
header with minimum height of 72px and if it's content overloads, the
header will auto-fit them
:root {
--header-min-height: 72px;
}
body {
margin: 0;
}
.root {
display: grid;
grid-template-rows: minmax(var(--header-min-height), auto) 1fr;
height: 100vh;
}
.header {
grid-row: 1;
background: darkcyan;
}
.content {
grid-row: 2;
display: flex;
background-color: palegreen;
overflow-y: hidden;
}
.content>div {
flex-grow: 1;
overflow-y: auto;
}
.white-space {
height: 3000px;
}
<div class="root">
<div class="header"></div>
<div class="content">
<div class="left">
Left Side
<div class="white-space"></div>
Left Side
</div>
<div class="right">
Right Side
<div class="white-space"></div>
Right Side
</div>
</div>
</div>
here's the example if it overloads.
:root {
--header-min-height: 72px;
}
body {
margin: 0;
}
.root {
display: grid;
grid-template-rows: minmax(var(--header-min-height), auto) 1fr;
height: 100vh;
}
.header {
grid-row: 1;
background: darkcyan;
}
.content {
grid-row: 2;
display: flex;
background-color: palegreen;
overflow-y: hidden;
}
.content>div {
flex-grow: 1;
overflow-y: auto;
}
.white-space {
height: 3000px;
}
.row {
display: flex;
flex-direction: row;
width: fit-content;
}
.item {
background: rgba(255, 255, 255, .5);
width: fit-content;
padding: 10px;
margin: 5px;
border-radius: 5px;
}
<div class="root">
<div class="header">
<div class="row">
<div class="item">test</div>
<div class="item">test</div>
<div class="item">test</div>
</div>
<div class="row">
<div class="item">test</div>
<div class="item">test</div>
<div class="item">test</div>
</div>
<div class="row">
<div class="item">test</div>
<div class="item">test</div>
<div class="item">test</div>
</div>
</div>
<div class="content">
<div class="left">
Left Side
<div class="white-space"></div>
Left Side
</div>
<div class="right">
Right Side
<div class="white-space"></div>
Right Side
</div>
</div>
</div>

How to vertically center align the bottom of a horizontal list of items of varying heights

I'm trying to achieve the following layout without using absolute positioning
The reason is that I would like to use css grid or flexbox as much as possible and try to avoid taking thins out of the flow if at all possible. In this case the surrounding div has a padding which should be respected, if it comes to that, and instead it should increase it's height if necessary. Usually I use max-content with css grid to achieve this.
If it was only the text it would have been as easy as align-items: center; however, because of the images/badges, the text will not properly align in the center if I do this.
https://stackblitz.com/edit/react-ts-t4h6ff?file=style.css
.list {
width : 100%;
background : red;
display : flex;
flex-direction : row;
align-items : center;
}
.list-item {
background : yellow;
display : grid;
grid-template-rows : max-content max-content;
padding : 1rem;
}
<div class="list">
<div class="list-item">list item 1</div>
<div class="list-item">
<div>image</div>
<div>list item 2</div>
</div>
<div class="list-item">
<div>image</div>
<div>list item 3</div>
</div>
</div>
Basically https://stackblitz.com/edit/react-ts-4xy14d?file=style.css is what I want to achieve, but without position absolute or transform translate.
Ended up with: https://stackblitz.com/edit/react-ts-78pckz?file=style.css
html,
body,
#root,
.wrapper {
height: 100%;
width: 100%;
}
.wrapper {
display: grid;
grid-template-rows: minmax(5rem, 50%) auto;
background: purple;
}
.list {
width: 100%;
background: red;
display: flex;
flex-direction: row;
height: 100%;
}
.list-item {
background: yellow;
display: grid;
grid-template-rows: 1fr max-content 1fr;
padding: 1rem;
box-sizing: border-box;
height: 100%;
overflow: hidden;
}
.image-wrapper {
position: relative;
}
.image {
max-width: 100%;
max-height: 100%;
position: absolute;
bottom: 0;
right: 0;
}
.text {
align-self: center;
white-space: nowrap;
}
<div class="wrapper">
<div class="list">
<div class="list-item">
<div> </div>
<div class="text">list item 1</div>
<div> </div>
</div>
<div class="list-item">
<div class="image-wrapper">
<img class="image" src="https://via.placeholder.com/100" />
</div>
<div class="text">list item 2</div>
<div> </div>
</div>
<div class="list-item">
<div class="image-wrapper">
<img class="image" src="https://via.placeholder.com/150" />
</div>
<div class="text">list item 3</div>
<div> </div>
</div>
</div>
<div>... :-)</div>
</div>
I don't think it's the most elegant solution, but here's how I would solve the problem (assuming your diagram is saying that the size of the images are going to be consistent).
Edit: Didn't quite get there with my answers, but it did help Dac0d3r come up with this final solution. Source from him is in the comments.
html,
body,
#root,
.wrapper {
height : 100%;
width : 100%;
}
.wrapper {
display : grid;
grid-template-rows : minmax(5rem, 50%) auto;
background : purple;
}
.list {
width : 100%;
background : red;
display : flex;
flex-direction : row;
height : 100%;
}
.list-item {
background : yellow;
display : grid;
grid-template-rows : 50% 50%;
padding : 1rem;
box-sizing : border-box;
height : 100%;
}
.image {
max-width : 100%;
max-height : 100%;
align-self : end;
}
<div class="wrapper">
<div class="list">
<div class="list-item">
<div></div>
<div class="text">list item 1</div>
</div>
<div class="list-item">
<img class="image" src="https://via.placeholder.com/100" />
<div class="text">list item 2</div>
</div>
<div class="list-item">
<img class="image" src="https://via.placeholder.com/150" />
<div class="text">list item 3</div>
</div>
</div>
</div>

Is it possible to draw vertical separators in the interior gaps of a CSS grid of varying columns?

I want to have a responsive grid of elements of variable length. The grid should fill the available width of the containing element, with the number of columns varying depending on the width of the container. This is straightforward to achieve using CSS grids; however, I don't know how to add a vertical border between columns (i.e., only in the interior column gaps). The below simple demo manages to achieve a vertical border in the event that there are three columns:
https://codepen.io/yowzadave/pen/OYPvLd?editors=1100
html, body {
box-sizing: border-box
}
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(24rem, 1fr));
grid-column-gap: 0.5rem;
}
.item {
border-right: 1px solid black;
padding-right: 0.5rem;
}
.item:nth-child(3n) {
border-right: none;
padding-right: 0;
}
.box {
background-color: pink;
height: 2rem;
margin: 0.5rem;
}
<html>
<body>
<div class="container">
<div class="item"><div class="box"></div></div>
<div class="item"><div class="box"></div></div>
<div class="item"><div class="box"></div></div>
<div class="item"><div class="box"></div></div>
<div class="item"><div class="box"></div></div>
<div class="item"><div class="box"></div></div>
</div>
</body>
</html>
...but in the event that the browser is wider or narrower, the borders will be misplaced. Is there a way to correctly place the borders at all browser widths?
You can use pseudo element on all the grid item where you will simply have overlap and be sure to cover all the gaps:
html,
body {
margin: 0;
}
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
grid-column-gap: 0.5rem;
overflow:hidden; /* Hide the overflow */
position:relative;
}
.item {
box-sizing: border-box;
position:relative;
}
.item:before {
content:"";
position:absolute;
top:0;
right:-0.25rem; /* Half the gap */
height:100vh; /* Big height*/
width:1px;
background:#000;
}
.box {
background-color: pink;
height: 2rem;
margin: 0.5rem;
}
<div class="container">
<div class="item">
<div class="box"></div>
</div>
<div class="item">
<div class="box"></div>
</div>
<div class="item">
<div class="box"></div>
</div>
<div class="item">
<div class="box"></div>
</div>
<div class="item">
<div class="box"></div>
</div>
<div class="item">
<div class="box"></div>
</div>
</div>

Full-width element breaks a layout created with display: grid

I have a simple layout that I've created with CSS grid consisting of a main element and a sidebar (please see snippet). Inside the sidebar, I have a child element that I would like to go full-width (i.e. ignore the padding around the layout container) on mobile devices.
The .full-width element does go full-width, but apparently what happens is it gets the whole grid to be 100vw, which makes main and aside overflow .container (the grey element). How can I keep it full-width and keep main and aside within the boundaries of .container? Another requirement is that the full-width element remains in the flow of the document (so no fixed or absolute positioning).
.page {
background: pink;
padding: 30px;
}
.container {
display: grid;
grid-template-areas: "aside" "main";
background: grey;
padding: 60px 0;
}
aside {
background: yellow;
}
main {
background: green;
}
.full-width {
width: 100vw;
margin-left: -30px;
background: red;
}
<div class="page">
<div class="container">
<main>
<p>I'm the main content</p>
</main>
<aside>
<p>I'm the sidebar</p>
<div class="full-width">
<p>I'm the full width element</p>
</div>
</aside>
</div>
</div>
First and easy solution is to set the columns to be 100% to avoid the overflow:
.page {
background: pink;
padding: 30px;
}
.container {
display: grid;
grid-template-areas: "aside" "main";
grid-template-columns: 100%;
background: grey;
padding: 60px 0;
}
aside {
background: yellow;
}
main {
background: green;
}
.full-width {
width: 100vw;
margin-left: -30px;
background: red;
}
body {
margin:0;
}
<div class="page">
<div class="container">
<main>
<p>I'm the main content</p>
</main>
<aside>
<p>I'm the sidebar</p>
<div class="full-width">
<p>I'm the full width element</p>
</div>
</aside>
</div>
</div>
Or simply use negative margin on both sides to have the full width you want:
.page {
background: pink;
padding: 30px;
}
.container {
display: grid;
grid-template-areas: "aside" "main";
background: grey;
padding: 60px 0;
}
aside {
background: yellow;
}
main {
background: green;
}
.full-width {
margin-left: -30px;
margin-right: -30px;
background: red;
}
body {
margin:0;
}
<div class="page">
<div class="container">
<main>
<p>I'm the main content</p>
</main>
<aside>
<p>I'm the sidebar</p>
<div class="full-width">
<p>I'm the full width element</p>
</div>
</aside>
</div>
</div>

Align <div> elements side by side

I know this is a rather simple question, but I can't figure it out for the life of me. I have two links which I've applied a background image to. Here's what it currently looks like (apologies for the shadow, just a rough sketch of a button):
However, I want those two buttons to be side by side. I can't really figure out what needs to be done with the alignment.
Here's the HTML
<div id="dB"}>
Download
</div>
<div id="gB">
Gallery
</div>
Here's the CSS
#buyButton {
background: url("assets/buy.png") 0 0 no-repeat;
display:block;
height:80px;
width:232px;
text-indent:-9999px;
}
#buyButton:hover{
width: 232px;
height: 80px;
background-position: -232px 0;
}
#buyButton:active {
width: 232px;
height: 80px;
background-position: -464px 0;
}
#galleryButton {
background: url("images/galleryButton.png") 0 0 no-repeat;
display:block;
height:80px;
width:230px;
text-indent:-9999px;
}
#galleryButton:hover{
width: 230px;
height: 80px;
background-position: -230px 0;
}
#galleryButton:active {
width: 230px;
height: 80px;
background-position: -460px 0;
}
Beware float: left… 🤔
…there are many ways to align elements side-by-side.
Below are the most common ways to achieve two elements side-by-side…
Demo: View/edit all the below examples on Codepen
Basic styles for all examples below…
Some basic css styles for parent and child elements in these examples:
.parent {
background: mediumpurple;
padding: 1rem;
}
.child {
border: 1px solid indigo;
padding: 1rem;
}
Using the float solution my have unintended affect on other elements. (Hint: You may need to use a clearfix.)
html
<div class='parent'>
<div class='child float-left-child'>A</div>
<div class='child float-left-child'>B</div>
</div>
css
.float-left-child {
float: left;
}
html
<div class='parent'>
<div class='child inline-block-child'>A</div>
<div class='child inline-block-child'>B</div>
</div>
css
.inline-block-child {
display: inline-block;
}
Note: the space between these two child elements can be removed, by removing the space between the div tags:
html
<div class='parent'>
<div class='child inline-block-child'>A</div><div class='child inline-block-child'>B</div>
</div>
css
.inline-block-child {
display: inline-block;
}
html
<div class='parent flex-parent'>
<div class='child flex-child'>A</div>
<div class='child flex-child'>B</div>
</div>
css
.flex-parent {
display: flex;
}
.flex-child {
flex: 1;
}
html
<div class='parent inline-flex-parent'>
<div class='child'>A</div>
<div class='child'>B</div>
</div>
css
.inline-flex-parent {
display: inline-flex;
}
html
<div class='parent grid-parent'>
<div class='child'>A</div>
<div class='child'>B</div>
</div>
css
.grid-parent {
display: grid;
grid-template-columns: 1fr 1fr
}
Apply float:left; to both of your divs should make them stand side by side.
keep it simple
<div align="center">
<div style="display: inline-block"> <img src="img1.png"> </div>
<div style="display: inline-block"> <img src="img2.png"> </div>
</div>
.section {
display: flex;
}
.element-left {
width: 94%;
}
.element-right {
flex-grow: 1;
}
<div class="section">
<div id="dB" class="element-left" }>
Download
</div>
<div id="gB" class="element-right">
Gallery
</div>
</div>
or
.section {
display: flex;
flex-wrap: wrap;
}
.element-left {
flex: 2;
}
.element-right {
width: 100px;
}
<div class="section">
<div id="dB" class="element-left" }>
Download
</div>
<div id="gB" class="element-right">
Gallery
</div>
</div>

Resources