Nested CSS grid and overflow-y - css

I'm building a chat application (imagine WhatsApp Web) where I have a scrolling content of messages and where always an input field is visible at the bottom.
For the sake for this question, I simplified the desired working behavior to this snippet:
<html lang="en" style="height: 100%">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body style="height: 100%; margin: 0">
<div
style="
display: grid;
height: 100%;
grid-template-rows: [messages] 1fr [input] 50px;
"
>
<div style="grid-row-start: messages; overflow-y: auto">
<div style="height: 1000px; width: 100px; background-color: red">
messages
</div>
</div>
<div style="grid-row-start: input; background-color: yellow">input</div>
</div>
</body>
</html>
In the example above, the content is scrollable and the yellow bar is always visible.
But as soon as the design is getting more complex (more layout around, also using CSS grids) the yellow bar is pushed down. So far, I could not figure out the reason for it. Here is an example with a surrounding grid:
<html lang="en" style="height: 100%">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body style="height: 100%; margin: 0">
<div style="display: grid; height: 100%; grid-template-rows: [chat] 1fr"><!--<--added level-->
<div style="grid-row-start: chat; height: 100%">
<div
style="
display: grid;
height: 100%;
grid-template-rows: [messages] 1fr [input] 50px;
"
>
<div style="grid-row-start: messages; overflow-y: auto; height: 100%">
<div style="height: 1000px; width: 100px; background-color: red">
messages
</div>
</div>
<div style="grid-row-start: input; background-color: yellow">
input
</div>
</div>
</div>
</div>
</body>
</html>
I tried to pass down the 100% height down but it didn't help either for the nested case. I also tried to use 100vh.
My goal is to avoid using calc() to reduce complexity and I also can't use a fixed height for the "messages" part.
Any ideas what I'm missing?

Just change the style of the first div after the body from: grid-template-rows: [chat] 1fr; to grid-template-rows: [chat] 100%; :
<html lang="en" style="height: 100%">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body style="height: 100%; margin: 0">
<div style="display: grid; height: 100%; grid-template-rows: [chat] 100%"><!--<--added level-->
<div style="grid-row-start: chat; height: 100%">
<div
style="
display: grid;
height: 100%;
grid-template-rows: [messages] 1fr [input] 50px;
"
>
<div style="grid-row-start: messages; overflow-y: auto; height: 100%">
<div style="height: 1000px; width: 100px; background-color: red">
messages
</div>
</div>
<div style="grid-row-start: input; background-color: yellow">
input
</div>
</div>
</div>
</div>
</body>
</html>

Related

how to make an auto row grid to add content

i want to make a automatic grid row, but i dont know hot to do that and i need to put grid-template-rows: repeat(10, 200px); i need to put repeat() to insert a new row whenever i need a new row, there's some way to turn it automatic
enter image description here
enter image description here
i thought to make a script to check it but i want a css way
*{
padding: 0;
border: 0;
margin: 0;
box-sizing: border-box;
list-style: none;
}
html, body{
width:100%;
height: 100%;
}
body *{
border: 1px solid rgb(21, 20, 20);
}
.grid{
width:100%;
height:100%;
display:grid;
grid-template-rows: 4.375rem calc(100% - 4.375rem);
grid-template-columns: 1fr;
}
.header{
}
.container{
display:grid;
grid-template-columns:14% 1fr;
}
.offers{
}
.content{
padding:10px;
display:grid;
grid-template-columns: 2fr 1fr 1fr 2fr;
grid-template-rows: repeat(10, 200px);
gap: 10px;
overflow: auto;
}
.card{
}
.card:nth-of-type(7n+4){
background-color: blue;
grid-row: span 2;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD#48,400,0,0" />
<title>Document</title>
</head>
<body>
<div class="grid grid-template">
<header class="header"></header>
<div class="container">
<aside class="offers"></aside>
<section class="content">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</section>
</div>
</div>
</body>
</html>

Avoid overlapping css grid elements

Trying to use grid for layout and I'd like to have different behavior between smaller and larger viewports. On larger viewports I want some content to be shown in a sidebar and tried using grid for this.
How can I prevent the overlapping of the First Card and Second Card when using grid-area like this?
.grid {
display: grid;
grid-template-columns: 10rem 1fr;
grid-column-gap: 1rem;
grid-template-areas:
"sidebar main"
;
max-width: 40rem;
margin: 10rem auto;
border: 1px solid gray;
}
.cards {
grid-area: main;
}
.card {
border: 1px solid red;
padding: 1rem;
}
.sidebar-content {
border: 1px solid green;
padding: 1rem;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="grid">
<div class="cards">
<div class="card">
First card
</div>
</div>
<div class="sidebar-content">
Sidebar Content
</div>
<div class="cards">
<div class="card">
Second card
</div>
<div class="card">
Third Card
</div>
</div>
</div>
</body>
</html>
I figured out something that works.
.grid {
display: grid;
grid-template-columns: 10rem 1fr;
grid-column-gap: 1rem;
grid-template-areas:
"sidebar first-quote"
"sidebar quotes"
;
max-width: 40rem;
margin: 10rem auto;
border: 1px solid gray;
}
.second-row {
grid-area: quotes;
}
.first-row {
grid-area: first-quote;
}
.card {
border: 1px solid red;
padding: 1rem;
margin-bottom: 1rem;
}
.sidebar-content {
border: 1px solid green;
padding: 1rem;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="grid">
<div class="first-row">
<div class="card">
First card
</div>
</div>
<div class="sidebar-content card">
Sidebar Content
</div>
<div class="second-row">
<div class="card">
Second card
</div>
<div class="card">
Third Card
</div>
</div>
</div>
</body>
</html>

How to centerd 2 columns in a 3 column template

I have grid section that has a grid-template-column for 3 columns. But this content is loaded dynamically so it has 2 columns sometimes. I am trying to center the columns when there is only 2 columns
I checked the documentation of the grid CSS and tried a lot of different CSS but nothing seems to work as I would like to.
.wrapper {
grid-template-columns: repeat(3,1fr);
display: grid;
align-items: stretch;
}
.items {
display: block;
}
Is this the behavior you were expecting?
More about flexbox: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
.parent {
display: flex;
justify-content: center;
}
/* Addition styling */
.parent {
padding: 30px;
background: lightgrey;
opacity: 0.8;
}
.child {
padding: 30px;
text-align: center;
background: black;
margin: 10px;
color: white;
max-width: 300px;
}
<div class="parent">
<div class="child">Column</div>
<div class="child">Column</div>
</div>
<hr>
<div class="parent">
<div class="child">Column</div>
<div class="child">Column</div>
<div class="child">Column</div>
</div>
<hr>
<div class="parent">
<div class="child">Column</div>
<div class="child">Column</div>
<div class="child">Column</div>
<div class="child">Column</div>
</div>
.grid-container {
display: grid;
grid-template-columns: repeat(3,1fr);
grid-column-gap: 50px;
grid-row-gap: 50px;
justify-content: center;
align-content: center;
}
.grid-container div {
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
<div class="grid-item">6</div>
<div class="grid-item">7</div>
<div class="grid-item">8</div>
<div class="grid-item">9</div>
</div>
</body>
</html>

Vertical Space Between Divs in Chrome not IE

Here's a backwards one.. IE Working while chrome does not!
I'm getting strange extra vertical spaces between divs in chrome. IE the divs sit flush against each other as intended.
I originally had a min-height attribute which caused some errors with width, but took that out. Still not entirely sure what's causing the spacing issue.
Any help is appreciated! Thanks all, -BR
CSS
#container {
width: 100%;
}
#headerout {
width: 100%;
height: 100px;
background: #1240AB;
}
#header {
width: 1000px;
margin: auto;
}
.splitout {
width: 100%;
height: 225px;
}
.split {
width: 1000px;
margin: auto;
}
.content {
width: 750px;
margin: auto;
}
.white {background-color: #DDE3F0;}
.lightblue {background-color: #C9D5F0;}
#footerout {
width: 100%;
height: 30px;
background: #1240AB;
}
#footer {
width: 1000px;
margin-left: 25px;
}
Markup
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset='utf-8'>
</head>
<body>
<div id="container">
<header>
<div id="headerout">
<div id="header">
<p>Content<p>
</div>
</div>
</header>
<div class="splitout white">
<div class="split">
<div class="content">
<p>content</p>
</div>
</div>
</div>
<div class="splitout lightblue">
<div class="split">
<div class="content">
<p>content</p>
</div>
</div>
</div>
<div class="splitout white">
<div class="split">
<div class="content">
<p>content</p>
</div>
</div>
</div>
</div>
<div id="footerout">
<div id="footer">
<p>foot</p>
</div>
</div>
</body>
</html>
Don't use css-reset.
Prefer normalize.css: http://necolas.github.io/normalize.css/
"reasons":
https://stackoverflow.com/a/8357635/1518921
this help with "bugs".
You need to use css-reset for paragraph's margins (they causing this)
http://jsfiddle.net/eUVm8/
Simple example of reset
* {
margin: 0;
padding: 0;
}
Chrome add's margins for paragraphs by default.

Creating an index page of empy divs only (no display, even after defining height/width)

I'm trying to create an index page that displays three rows of 7 squares. It sounds lame, but I have some jQuery ideas I think will eventually make it look pretty cool. I thought creating empty divs for the squares would do the trick and would allow me to simply define the sizes (heights and widths) of all the divs. Problem: can't get them to display.
I read lots of other questions about this problem, but the fix was always to define a width for the div, but this hasn't worked for me. I also looked into setting this up as a table, since that's basically what I want it to look like, but MDN shows as "not recommended for layout," and I'd like to write code that's up to snuff.
I compared my code to some of the code I saw in a jQuery lesson in codecademy, and I can't see any real difference that would cause the codecademy code to display squares and mine to display nothing. Any help or suggestions about how to address this problem and get my vision to render on the page would be great! Thanks.
Here's the html:
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Test Page</title>
<link rel="stylesheet" type="text/css" href="styles/main.css">
</head>
<body>
<container class="row">
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
</container>
<container class="row">
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
</container>
<container class="row">
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
</container>
</body>
</html>
And the CSS:
body {
background-color: gray;
height: 100%;
width: 100%;
}
.row {
width: 600px;
height: 100px;
padding: 1em;
text-align: center;
}
.sqtop {
height: 20px;
width: 20px;
min-height: 10px;
min-width: 10px;
color: black;
background-color: yellow;
border-radius: 5px;
position: absolute;
display: inline-block;
vertical-align: middle;
}
Your absolute positioning is messing with the layout. Basically since all of the divs have an absolute position, they all show atop of each other.
Another problem is that you're only styling one of the rows, while the other two have no CSS attributes attached to them.
Here is a fix for the CSS:
body {
background-color: gray; height: 100%; width: 100%; }
.row {
width: 600px; height: 100px; padding: 1em; text-align: center; }
.sqtop, .sqmid, .sqbtm {
height: 20px; width: 20px; min-height: 10px;
min-width: 10px; color: black; background-color: yellow; display:
inline-block; border-radius: 5px; vertical-align: middle; }
This doesn't solve all of the problems though. The boxes still need to be in rows. Since the div's dont know exactly where where a line break should be, you can add a div that will create a line break in the HTML. This is how it would look like:
<container class="row">
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
<div class="sqtop"></div>
</container>
<div style="clear:both"></div>
<container class="row">
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
<div class="sqmid"></div>
</container>
<div style="clear:both"></div>
<container class="row">
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
<div class="sqbtm"></div>
</container>
That should give you 3 rows with 7 divs.
remove absolute position, http://jsfiddle.net/ZG7jZ/
.sqtop {
height: 20px;
width: 20px;
min-height: 10px;
min-width: 10px;
color: black;
background-color: yellow;
border-radius: 5px;
/*position: absolute;*/
display: inline-block;
vertical-align: middle;
}
The problem is that you're only applying your styling to sqtop. Try this:
body {
background-color: gray;
height: 100%;
width: 100%;
}
.row {
padding: 1em;
text-align: center;
overflow: hidden;
}
.row>div {
height: 20px;
width: 20px;
color: black;
background-color: yellow;
border-radius: 5px;
vertical-align: middle;
display: inline-block;
}
http://jsfiddle.net/keurr/1/

Resources