css grid to fill 100vh without affecting row height - javascript

I have a grid with 3 columns and a variable/dynamic number of rows. The grid has a colored background and when there are NOT enough rows as to vertically fill the window, the remaining, empty vertical space is un-colored:
.grid {
align-self: flex-start;
display: grid;
grid-template-columns: min-content 2fr 1fr;
grid-gap: 0px;
}
.index, .title {
background: red;
padding: 0 2vw 0 1vw;
}
.ticker {
background: yellow;
}
<div class="grid">
<div class="index">1</div>
<div class="title">Pigs are cute</div>
<div class="ticker">blah blah</div>
<div class="index">2</div>
<div class="title">Horses rise at night</div>
<div class="ticker">bleh bleh</div>
<div class="index">3</div>
<div class="title">Cats run in packs</div>
<div class="ticker">blih blih</div>
</div>
I would like this vertical space to be colored as the grid is. The apparently obvious solution is to give the grid a height of 100vh. But this expectedly stretches each row's height accordingly, which is not the result I am looking for, as I need row height to adapt to content.
.grid {
align-self: flex-start;
display: grid;
grid-template-columns: min-content 2fr 1fr;
grid-gap: 0px;
height: 100vh;
}
.index, .title {
background: red;
padding: 0 2vw 0 1vw;
}
.ticker {
background: yellow;
}
<div class="grid">
<div class="index">1</div>
<div class="title">Pigs are cute</div>
<div class="ticker">blah blah</div>
<div class="index">2</div>
<div class="title">Horses rise at night</div>
<div class="ticker">bleh bleh</div>
<div class="index">3</div>
<div class="title">Cats run in packs</div>
<div class="ticker">blih blih</div>
</div>
Is there any CSS grid way of expanding the grid vertically while still allowing row height to adapt to content?
An alternative javascript solution, such as adding blank rows to the grid until grid's height is >= the height of the window would also be acceptable.
A flex solution is, I believe, not acceptable, as I need a grid-like behaviour where columns and rows remain aligned.
Thank you

Since different columns have different colors, extending the grid would not work, because the grid itself can't have two different colors. This means only expanding the rows or adding new rows would work.
Since one of the question's requeriments is to leave row height untouched, and as per this question, adding an extra row and expanding only that row to take the remaining space is not possible with CSS grid (but flexbox), the only solution seems to add rows via JS until the grid height is >= window height :
var rowHeight = window.getComputedStyle(document.querySelector('.grid').firstElementChild).height;
var row = "<div class='index' style='height:"+ rowHeight +"'></div><div class='title' style='height:"+ rowHeight +"'></div><div class='ticker' style='height:"+ rowHeight +"'></div>";
while (parseFloat(window.getComputedStyle(document.querySelector('.grid')).height) < window.innerHeight) {
document.querySelector('.grid').innerHTML += row;
}
html, body {
margin: 0;
padding: 0;
}
.grid {
align-self: flex-start;
display: grid;
grid-template-columns: min-content 2fr 1fr;
grid-gap: 0px;
}
.index, .title {
background: red;
padding: 0 2vw 0 1vw;
}
.ticker {
background: yellow;
}
<div class="grid">
<div class="index">1</div>
<div class="title">Pigs are cute</div>
<div class="ticker">blah blah</div>
<div class="index">2</div>
<div class="title">Horses rise at night</div>
<div class="ticker">bleh bleh</div>
<div class="index">3</div>
<div class="title">Cats run in packs</div>
<div class="ticker">blih blih</div>
</div>

Related

How to make two columns same height dynamically

I hava a page with two columns. I would like to textarea height mimic left column height. Left column is short when webpage loads, but when user starts expanding various properties (checkboxes + dropdownmenus) it grows based on hidden divs. But my textarea is still small in right column and making it staticly bigger does not look good.
I want it to grow per left column height. Not sure how to achieve that.
EDIT:
Once height: 100%; was added to textarea it solved the issue with columns growth.
But I ran into another two issues.
Textarea in right column overlaps that column on page load. When I try to resize, it suddenly jumps to the column properly. Weird behavior.
here is the pic - textarea overlaps column
Left column context is not aligned properly with right. How I am going to align or justify context of both columns so they end up like this:
here is the pic - final look
My CSS:
body {
height: 100%;
position: relative;
background: #000000;
color: #66adff;
font-size: 105%;
font-family: serif, Arial, Helvetica
}
.column {
border: 5px solid #333;
}
.container{
display: flex;
}
.columnleft {
width: 45%;
padding: 10px;
display: table-cell;
}
.columnright {
width: 45%;
padding: 10px;
display: table-cell;
}
textarea.out {width: 100%; height: 100%; box-sizing: border-box;}
EDIT 2:
Issue 1 - I had text inside the column which pushed area down
Issue 2 - all was fixed with proper padding
Thanks all for replies.
I think you could do this without js, but use CSS Grid instead.
Example:
.grid-container {
display: grid;
grid-template-columns: 1fr 1fr; // the width of each column
grid-template-rows: auto; // row height will auto-adjust to contents
}
<div class="grid-container">
<div class="column-left">
...some dynamic content
gets bigger and bigger and bigger and bigger and bigger
</div>
<div class="column-right">
might be empty or small or large
</div>
</div>
The grid row height will always adjust to the height of the largest content which will make both columns the same height.
Since you're using flex, the right column should be automatically adjusting to match the left column. It sounds like your issue is that the textarea is not expanding automatically to match its container (right column.)
If that's the case, try this simple fix - in your CSS, set textarea height to 100% to automatically fill its parent:
textarea {
height: 100%;
};
Here's an example answer:
Textarea to fill a parent container exactly, with padding
The reason your code wasn't working was because you didn't set the height to your textarea settting the height to 100% will always make it fit the maximum size of it's container (<div>) also i have added box-sizing: border-box; so that you can add padding to your columnright.
A better explanation about box-sizing can be found here (just won't explain here because i couldn't do better then this): https://css-tricks.com/box-sizing/
function f_anyEvent(){
var leftcolumnHeight = document.getElementById('columnleft').style.height.value;
if (document.getElementById('columnleft').style.height != document.getElementById('columnright').style.height)
document.getElementById('columnright').style.height = leftcolumnHeight.value;
}
document.getElementById('add').addEventListener('click', function() {
let columnleft = document.getElementById('columnleft');
columnleft.innerHTML += '<h1>a</h1>';
});
.row{
display: flex;
}
.column {
border: 1px solid #333;
}
.columnleft {
float: left;
width: 45%;
padding: 10px;
display: table-cell;
}
.columnright {
float: left;
width: 45%;
padding: 10px;
display: table-cell;
}
textarea {
width: 100%;
height: 100%;
box-sizing: border-box;
}
<div class="row">
<div id="columnleft" class="column columnleft">
</div>
<div id="columnright" class="column columnright">
<textarea></textarea>
</div>
</div>
<button id="add">
add
</button>
Every time you click add it will add an <h1> to your left column and your textarea will get the same height as columnleft.
Here's a basic demo of an interface similar to yours that uses display: grid on the parent container to automagically keep the two inner divs the same height. (Click on the blue details element to trigger a height change.)
It's wonderfully simple. (Thanks for inspiring me to finally learn how grid works.)
// The JavaScript isn't needed for the dynamic styling. (It just copies the text.)
const
left = document.getElementById("left"),
right = document.getElementById("right");
left.addEventListener("change", showOutput);
function showOutput(event){
right.innerHTML = this.querySelector("#reasons").value
}
div { max-width: 400px; border: 1px solid grey; }
details{ margin: 10px 5px; color: #0000DD; text-decoration: underline; }
/* This is where the magic happens */
#container { display: grid; grid-template-columns: 1fr 1fr; }
#left{ padding: 10px; }
#right { white-space: pre-wrap; }
<div id="container">
<div id="left">
<label> <input type="checkbox"/> I like pie </label>
<details>
<summary>Type your reasons here</summary> <textarea id="reasons"></textarea>
</details>
</div>
<div id="right"></div>
</div>

CSS - How do I create a grid that takes up the remaining width of screen (without counting sidebar)

I am trying to create a grid in CSS, but I am not sure how to specify the width of the entire grid, such that it takes up only the remaining width of the screen (minus the sidebar) such that there should not be any scrolling horizontally allowed. Below is the screenshot of the issue I am facing.
As you can see, there is horizontal scrolling enabled, because the grid is too wide.
Here is my code for reference: (I am using ReactJS)
.analytics-grid {
display: grid;
grid-template-rows: auto;
grid-template-columns: 1fr 1fr;
row-gap: 10px;
column-gap: 10px;
grid-template-areas: "conversion conversion-daily"
}
.daily-conversion-box {
grid-area: conversion-daily;
padding: 20px;
}
.conversion-box {
grid-area: conversion;
padding: 20px;
}
jsx (where CustomerConversion and CustomerConversionDaily are child components I call to render the charts)
<div className='analytics-grid'>
<div className='conversion-box'>
<CustomerConversion />
</div>
<div className='daily-conversion-box'>
<CustomerConversionDaily />
</div>
sidebar.js (where Sider is a component from a UI package AntD)
<div>
<Sider trigger={null} collapsible collapsed={collapsed}>
{menu()}
</Sider>
<div id='crm-header-layout'>
... *header goes here* ...
<div id="crm-content">
{props.children} //this is where the analytics grid from above end up
</div>
</div>
</div>
Is there a way for me to be able to specify the width of my grid such that it just nice takes up the remaining width of the screen minus the sidebar such that there is no horizontal scrolling to be done? Thanks all for the help, I am new to CSS, so do guide me along if there are any better solutions to accomplish what I want to accomplish! Thank you
when you set display: grid; it means the children of this node are arranged using grid. It doesn't set the div's height or width for you. You need to set it if you want to contain it.
There are multiple ways to set the width.
You can use the grid the same way you've used for container. Like this,
.container {
display: grid;
grid-template: 1fr / 80px 1fr;
}
.content-1 {
background-color: red;
}
.content-2 {
background-color: blue;
}
<div class="container">
<div class="content-1">Content 1</div>
<div class="content-2">Content 2</div>
</div>
You can contain both the appbar and the content in a flex, and set the flex-grow of container to 1.
.app{
display: flex;
}
.appbar{
flex-grow: 0;
}
.main-container{
flex-grow: 1;
}
or,
use CSS calc for container like this.
.analytics-grid {
display: grid;
grid-template-rows: auto;
grid-template-columns: 1fr 1fr;
row-gap: 10px;
column-gap: 10px;
grid-template-areas: "conversion conversion-daily";
width: calc(100vw - <appbar width>);
}
PS: grid-template is short hand to set both row and columns at a time. Refer https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template

Expand DIV element from Right to Left with a grid layout and floats

I am not sure that this is entirely possible. I am using display:grid to build the layout of my page and I know that I can't use float with grid items, however I am trying to manipulate content inside of a grid item with floats and that doesn't appear to be working either.
My layout basically boils down to this:
<html>
<head>
<style>
.page-container{
display:grid;
grid-template-columns: 4fr .25fr;
grid-template-rows: repeat(3, 1fr);
height:100vh;
}
.menu{
grid-column: 2 / span 1;
grid-row: 2 / span 2;
}
</style>
</head>
<body>
<div class="page-container">
<div class="menu">
<div style="background-color:#000;width:100%;height:50px;margin-bottom:25px;"></div>
<div style="background-color:#000;width:100%;height:50px;margin-bottom:25px;"></div>
<div style="background-color:#000;width:100%;height:50px;margin-bottom:25px;"></div>
</div>
</div>
</body>
</html>
CodePen Example
What I want to have happen is that when a user hovers over any of the items in the menu div I want the width to transition to 200px (or some other width that is not relative to the container). I specifically want the right edge of the div to be anchored so that the width grows from right to left, rather than left to right. This is easy enough to do by using right: 0 however this causes the grid column to expand as well thus shrinking the first column. Instead I would like the divs to expand outside of the menu container's width thus overlapping column 1 and column 2 in the overall grid.
Is there a way to achieve this using CSS and/or JavaScript? I would prefer a CSS solution but either would work.
You can animate margin-left with a negative value:
.page-container {
display: grid;
grid-template-columns: 4fr .25fr;
grid-template-rows: repeat(3, 1fr);
height: 100vh;
}
.menu {
grid-column: 2 / span 1;
grid-row: 2 / span 2;
}
.menu>div {
background-color: #000;
height: 50px;
margin-bottom: 25px;
transition:all 1s;
margin-left:0;
}
.menu>div:hover {
margin-left:-200px;
}
<div class="page-container">
<div class="menu">
<div></div>
<div></div>
<div></div>
</div>
</div>

CSS Grid - Check if grid row has empty cells and fill

I wasn't able to find a solution for the following:
I've created a grid layout (320px each row), max 4 rows, changing rows via media queries.
.container {
display: grid;
grid-template-columns: 320px;
grid-template-rows: 50px;
grid-auto-rows: 50px;
grid-column-gap: 20px;
grid-row-gap: 4px;
grid-auto-flow: row dense;
}
I am filling this container with content from an API. The divs to fill into the container have two different sizes (320px by 300px) or (660px by 300px). Like a Masonry Layout with infinity scrolling. By design it has, depending on the content sometimes gaps in the layouts.
My question is: How can I check if a grid-row is empty and fill in a placeholder-div (company logo, ...).
Thanks in advance.
Edit: Add image to show issue
you mean this ?
$(".container").each(function(index, el) {
if ($(el).is(':empty')) $(el).html("is empty");
})
.container {
display: grid;
grid-template-columns: 320px;
grid-template-rows: 50px;
grid-auto-rows: 50px;
grid-column-gap: 20px;
grid-row-gap: 4px;
grid-auto-flow: row dense;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container"></div>
<div class="container">test</div>
<div class="container">test</div>
<div class="container"></div>
<div class="container">test</div>
You can use JQuery to check if the dev is empty, for example
if ($('.classNameOne').html() == "") {
//Do something useful here
});

How to use a position:relative DIV act as a 'spacer' for other divs?

I have a container with a bunch of equally sized elements. The container has a width of 100% up to a certain px amount, so if a user shrinks their screen down, elements from the first row may be moved down to the second row to fit, and from the second row to the third row, etc.
I'd like the .spacer div to act as a pseudo margin so that the first element in the second row of divs, no matter what div it actually is, will be spaced 250px out from the left side of the container. I want that .spacer div to always remain at a fixed point relative to the container (right at the beginning of the second row) but also affect the position of the first div in that row. How can I accomplish this with CSS? Open to JS solutions as well.
Here's a Codepen that shows the situation I'm describing:
https://codepen.io/anon/pen/QMMyLj
Any ideas?
Not sure, but check if you are looking something like this:
.container {
background-color: black;
width: 80%;
max-width: 1800px;
min-height: 1000px;
padding: 10px 5px;
text-align: center;
margin: 0 auto;
}
.square {
display: inline-block;
height: 250px;
width: 250px;
background-color: white;
float: none;
margin-left: 5px;
margin-right: 5px;
margin-bottom: 20px;
text-align: center;
line-height: 250px
}
<div class="container">
<div class="square">1</div>
<div class="square">2</div>
<div class="square">3</div>
<div class="square">4</div>
<div class="square">5</div>
<div class="square">6</div>
<div class="square">7</div>
<div class="square">8</div>
<div class="square">9</div>
<div class="square">10</div>
<div class="square">11</div>
<div class="square">12</div>
<div class="square">13</div>
<div class="square">14</div>
<div class="square">15</div>
</div>
Here is a possible solution using css grid and variables. It uses css-grid to layout the red spacer, and javascript to update the number of columns required. (Note that they are only supported in modern browsers http://caniuse.com/css-grid/embed)
CSS
:root {
--colNum: 1;
}
.container {
display: grid;
justify-content: left;
grid-template-columns: repeat(var(--colNum), auto);
}
.square {
height: 250px;
width: 250px;
background-color: white;
}
.spacer {
background-color: red;
width: 250px;
grid-row: 2 / span 1;
grid-col: 1 / span 1;
}
JS
function setNoOfColumns(){
columns = Math.floor(window.innerWidth / 250);
document.documentElement.style.setProperty("--colNum", columns);
}
window.addEventListener("resize", function(){
setNoOfColumns();
});
setNoOfColumns();
Code: https://codepen.io/anon/pen/mMMPwO

Categories