Have table row scrollable - html

Currently facing some problems with the layout I want to accomplish.
How can I divide my page in such a way that the header row gets the height it needs ( for it's content ) and all the rest is given to the images row? A bit like auto, 100% if that is possible? For testing I've given it a fixed height.
The text in the header row should be bottom alligned vertically but somehow this is not working?
And lastly, how can I get the images row scrollable in such a way that the header row stays fixed? So not sticky for the header, because then the header will also partially scroll. The complete content of the header should stay fixed and only the images content should scroll on Y value. ( so no horizontal scroll )
body {
font-size: 18px;
max-width: 820px;
margin: 0 auto;
}
.table {
display:table;
width:100%;
}
.row {
display:table-row;
}
.row.header {
height:80px;
vertical-align: bottom;
}
.row.images {
overflow: scroll;
}
.column {
display: table-cell;
width: 50%
}
.column.left {
padding-left: 10px;
}
.column.right {
text-align: right;
padding-right: 10px;
}
<body>
<div class="table">
<div class="row header">
<div class="column left">Portfolio</div>
<div class="column right">Artist</div>
</div>
<div class="row images">
<div class="grid">
<div class='grid__col-sizer'></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/orange-tree.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/submerged.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/look-out.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/one-world-trade.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/drizzle.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/cat-nose.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/contrail.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/golden-hour.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/flight-formation.jpg"></div>
</div>
</div>
</div>
</body>

Solved my own problems, using CSS grid. The complete codepen is available here: https://codepen.io/depechie/pen/jOBGrRP
body {
font-family: "Helvetica Neue", Arial, sans-serif;
font-size: 0.8rem;
margin: 0;
}
.page {
display: grid;
grid-template-rows: auto;
grid-template-columns: 1fr;
height: 100vh;
}
.panel {
display: grid;
/* grid-template-rows: var(--bar-height) 1fr; */
grid-template-rows: auto 1fr;
height: 100vh;
}
.panel-body {
overflow-y: auto;
display: grid;
justify-content: center;
}
.tabs {
display: grid;
grid-template-columns: repeat(2, 1fr);
height: 100%;
padding: 20px;
}
.tab-item.left {
text-align: left;
}
.tab-item.right {
text-align: right;
}

You can Use height: fit-content; To make the height of the div fit the height of the elements it has
code:
body {
font-size: 18px;
max-width: 820px;
margin: 0 auto;
}
.table {
display:table;
width:100%;
}
.row {
display:table-row;
}
.row.header {
/* here you can replace fixed hight with : fit-height */
height:fit-height;
display: flex;
vertical-align: bottom;
}
.row.images {
overflow: scroll;
}
.column {
display: table-cell;
width: 50%
}
.column.left {
padding-left: 10px;
}
.column.right {
text-align: right;
padding-right: 10px;
}
<body>
<div class="table">
<div class="row header">
<div class="column left">Portfolio</div>
<div class="column right">Artist</div>
</div>
<div class="row images">
<div class="grid">
<div class='grid__col-sizer'></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/orange-tree.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/submerged.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/look-out.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/one-world-trade.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/drizzle.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/cat-nose.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/contrail.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/golden-hour.jpg"></div>
<div class="grid__item"><img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/flight-formation.jpg"></div>
</div>
</div>
</div>
</body>

Related

Div under grid in flexbox

I have a layout that is a sidebar and a grid both wrapped in a flexbox. I'd like to put a div underneath the grid so it can have prev/next buttons, like in this image, but I can't figure out how to do that. The grid resizes itself with the window so the grid can take as many rows as necessary and then the div should go below that, and be as wide as the grid.
This is what I have, but the div is on the right of the grid:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Boardgame Database</title>
<style>
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
aside {
background-color: red;
flex: 1;
min-width: 250px;
}
.grid-container {
flex: 4;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
#flex-container {
display: flex;
flex-direction: row;
min-height: 100vh;
}
</style>
</head>
<body>
<div id="flex-container">
<aside class="sidebar">
</aside>
<section 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 class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>
Checkout the following Code.
#main{
display :flex;
}
#sidebar{
width:70px;
height: 300px;
border: solid black 1px;
}
#grid-area{
width:200px;
height: 300px;
border: solid black 1px;
display: block;
}
#grid{
width:200px;
height: 250px;
border: solid black 1px;
display: block;
}
<div id="main">
<div id="sidebar"></div>
<div id="grid-area">
<div id="grid"></div>
<div id="button">next / prev</div>
</div>
</div>
You should use nested flex containers. Section and bottom div should be wrapped inside another flex container with flex direction to column.
So outer flex will make sidebar & inner flex container to be side by side.
Or just use a normal div container instead of flex.
here is another example only with grid keeping the pre/next button at the bottom of the viewport:
body {
margin: 0;
}
#grid-container {
display: grid;
height: 100vh;
grid-template-columns: minmax(250px, 1fr) 4fr;
grid-template-rows: 1fr auto;
}
aside {
background-color: red;
border: 1px solid;
margin: 0.25em;
grid-row: span 2;
grid-column: 1;
}
section,
#page-buttons {
grid-column: 2;
border: solid 1px;
margin: 0.25em;
}
section {
overflow: auto;
}
#page-buttons {
display: flex;
gap: 1em;
padding: 0.5em;
background: lightgray;
justify-content: center;
}
.grid-item {
border: 1px solid black;
padding: 20px;
font-size: 24px;
text-align: center;
overflow: hidden;
}
<div id="grid-container">
<aside class="sidebar">
</aside>
<section 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 class="grid-item">10</div>
<div class="grid-item">11</div>
<div class="grid-item">12</div>
<div class="grid-item">13</div>
<div class="grid-item">14</div>
<div class="grid-item">15</div>
<div class="grid-item">16</div>
<div class="grid-item">17</div>
<div class="grid-item">18</div>
</section>
<div id="page-buttons">
prev
next
</div>
</div>

How to change column span to row span by CSS FLEX for RWD

I want to use same HTML structure to display a Table that made of FLEX on the desktop and mobile, but I have no idea to change column span to row span, I know position: absolute it's not a good idea for maintaining
codepen
.wrapper {
display: flex;
}
.block {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
.block1 {
background-color: cadetblue;
}
.block2 {
background-color: cornflowerblue;
}
.block3 {
background-color: beige;
}
.col-span {
height: 100%;
}
/* row span */
.row-span-sample {
position: relative;
}
.row-span {
width: 200%;
position: absolute;
left: -100%;
}
<h1>column span on Desktop</h1>
<div class="wrapper">
<div class="row">
<div class="block block1 col-span">1</div>
</div>
<div class="row">
<div class="block block2">2</div>
<div class="block block3">3</div>
</div>
</div>
<h1>row span on mobile</h1>
<div class="wrapper">
<div class="row row-span-sample">
<div class="block block1">1</div>
</div>
<div class="row row-span-sample">
<div class="block block2">2</div>
<div class="block block3 row-span">3</div>
</div>
</div>
Can I change it without position: absolute?
Here's a very simple solution using CSS Grid Layout and a media query.
No absolute positioning.
No nested containers.
.wrapper {
display: grid;
grid-template-columns: 200px 200px;
grid-template-rows: 200px 200px;
grid-template-areas:
"one two"
"one three";
}
#media (max-width: 700px) {
.wrapper {
grid-template-areas:
"one two"
"three three";
}
}
.block1 { grid-area: one; background-color: cadetblue; }
.block2 { grid-area: two; background-color: cornflowerblue; }
.block3 { grid-area: three; background-color: beige; }
.block {
display: flex;
justify-content: center;
align-items: center;
font-size: 2em;
}
<div class="wrapper">
<div class="block block1">1</div>
<div class="block block2">2</div>
<div class="block block3">3</div>
</div>
revised codepen
You can do this:
.wrapper {
display: flex;
}
.block {
width: 50px;
height: 50px;
display: flex;
justify-content: center;
align-items: center;
}
.block1 {
background-color: cadetblue;
}
.block2 {
background-color: cornflowerblue;
}
.block3 {
background-color: beige;
}
.col-span {
height: 100%;
}
/* row span */
.row-span-sample {
position: relative;
}
.row-span {
width: 200%;
position: relative;
left: 0;
left: -100%;
}
<h1>column span on Desktop</h1>
<div class="wrapper">
<div class="row">
<div class="block block1 col-span">1</div>
</div>
<div class="row">
<div class="block block2">2</div>
<div class="block block3">3</div>
</div>
</div>
<h1>row span on mobile</h1>
<div class="wrapper">
<div class="row row-span-sample">
<div class="block block1">1</div>
</div>
<div class="row row-span-sample">
<div class="block block2">2</div>
<div class="block block3 row-span">3</div>
</div>
</div>
What have I done? Just change absolute value from position property, and change it to relative.
And the set left property to 0.
And why this works? Because, if you have a position defined (relative or absolute) then you can set the position (because we are get used to set them only when absolute positions are present).
Also, you can set it without left: 0; statment. Relative positions are better than absolute ones, but you need to know how them works.

How to align cascaded div containers with Flexbox

I am trying to achieve the following layout for a navigation bar with Flexbox. I am stuck with the alignment of the divs. This is how it should like:
This is what i build up with Divs and CSS. But i dont know how to align those divs, so that i get the desired result.
Fiddle
* {
box-sizing: border-box;
}
#nav {
display: flex;
}
#logo {
width: 100px;
heigth: 100px;
background-color: black;
margin-left: 24px;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>
I would add a few more flex containers to some of the child divs. I'd also specify the width and flex-direction on the #left_side div and justify the content on the #top_nav div.
Try the snippet below or see this updated fiddle:
* {
box-sizing: border-box;
}
#nav,
#left_side,
#top_nav,
#bottom_nav {
display: flex;
}
#left_side {
flex-direction: column;
width: 100%;
}
#top_nav {
justify-content: space-between;
}
#logo {
width: 100px;
heigth: 100px;
background-color: black;
margin-left: 24px;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>
There are many good guides to flexbox available. This one is very good: https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Your layout can be achieved by adding the following CSS
fiddle
* {
box-sizing: border-box;
}
#nav {
display: flex;
}
#logo {
width: 100px;
height: 100px;
background-color: black;
margin-left: 24px;
}
#left_side {
display: flex;
flex-direction: column;
flex: 1;
}
#top_nav {
display: flex;
justify-content: space-between;
flex: 1;
}
#bottom_nav {
display: flex;
flex: 1;
}
<div id="nav">
<div id="logo">
100x100px Logo
</div>
<div id="left_side">
<div id="top_nav">
<div id="title">TITLE OF PAGE</div>
<div id="menu_swith">SWITCH</div>
</div>
<div id="bottom_nav">
<div class="nav_item">Menu 1</div>
<div class="nav_item">Menu 2</div>
<div class="nav_item">Menu 3</div>
<div class="nav_item">Menu 4</div>
</div>
</div>
</div>
Flexbox is one way to build the layout. You'll need extra containers to make it work.
However, if you want to keep it really simple, use CSS Grid:
header {
display: grid;
grid-template-columns: 100px 3fr 1fr;
grid-template-rows: 50px 50px;
grid-template-areas: " logo title switch "
" logo nav nav ";
}
#logo { grid-area: logo; }
#title { grid-area: title; }
#menu_switch { grid-area: switch; }
nav { grid-area: nav; display: flex; }
nav > a {
flex: 0 0 75px;
margin: 5px;
border: 2px solid green;
}
/* for demo only */
#logo { background-color: lightgray; }
#title { background-color: pink; }
#menu_switch { background-color: skyblue; }
nav { background-color: lightgreen; }
* { box-sizing: border-box; }
div, a { display: flex; align-items: center; justify-content: center;
text-align: center; }
<header>
<div id="logo">100x100px<br>Logo</div>
<div id="title">Page Title</div>
<div id="menu_switch">Switch</div>
<nav>
<a class="nav_item">Menu 1</a>
<a class="nav_item">Menu 2</a>
<a class="nav_item">Menu 3</a>
<a class="nav_item">Menu 4</a>
</nav>
</header>
jsFiddle demo
For an explanation of the grid rules above and browser support data, see these posts:
CSS-only masonry layout but with elements ordered horizontally
Browser support for CSS Grid

Using %-based width divs inside a container with px-based margin

Bit of a beginner's question here - I'm sure it's been asked many times over but not knowing how to phrase the question means I've found it hard to find answers.
I'm trying to create 3 "cards" in a div which are responsive. I would like the margin between the cards to stay at 20px.
This is what I've come up with so far - the contents of the card container should add up to 965, so I'm not sure what's causing it to break and spill out, unless I'm doing something else wrong.
.container {
max-width: 1280px;
}
.card-container {
max-width: 965px;
padding: 0 20px;
display: block;
float: left;
}
.card {
width: 33%;
min-width: 295px;
}
.one {
width: 100%;
height: 200px;
background-color: #333;
display: block;
float: left;
}
.card + .card {
margin: 0px 0px 0px 20px;
}
<div class="container">
<div class="card-container">
<div class="card">
<div class="one"></div>
</div>
<div class="card">
<div class="one"></div>
</div>
<div class="card">
<div class="one"></div>
</div>
</div>
<!-- <div class="map-card"></div> -->
</div>
Thanks for any help, or redirecting to a similar topic.
You can use flex like this https://jsfiddle.net/3gg8ngm2/2/:
.container {
max-width: 1280px;
}
.card-container {
max-width: 965px;
padding: 0 20px;
display: flex;
}
.card {
width: 33%;
/* min-width: 295px; */
}
.one {
width: 100%;
height: 200px;
background-color: #333;
display: block;
float: left;
}
.card + .card {
margin: 0px 0px 0px 20px;
}
<div class="container">
<div class="card-container">
<div class="card">
<div class="one"></div>
</div>
<div class="card">
<div class="one"></div>
</div>
<div class="card">
<div class="one"></div>
</div>
</div>
<!-- <div class="map-card"></div> -->
</div>
Or you can also use display-inline-block to your .card class.
There is a solution based on display: flex
.container {
width: 600px;
}
.card-container {
display: flex;
background: yellow;
}
.card {
width: calc(33% - 20px);
margin-right: 20px;
}
.card:first-child {margin-left:20px}
.one {
height: 200px;
background-color: #333;
}
<div class="container">
<div class="card-container">
<div class="card">
<div class="one">1</div>
</div>
<div class="card">
<div class="one">2</div>
</div>
<div class="card">
<div class="one">3</div>
</div>
</div>
</div>
Add this
.card {
width: 30%;
float:left;
min-width: 295px;
}
and will resolve your issue.

How to set right spacing between inline-block elements

My example:
Its possilble to set same spacing between div inline elements. Because auto width is not working.
This is what i got so far:
HTML
<div id="frame">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
<div class="block">4</div>
</div>
</div>
CSS
#frame div {
background-color: brown;
padding-left: 20%;
padding-right: 20%;
width: auto;
margin: 5px;
display: inline-block;
}
Width of frame is full screen and width of block have to fit inside this frame, its not that important.
In that case you can avoid the not yet that well supported flex and use percentages instead:
Give 20% width to each of the .block divs
Give 4% margin-right to each of the .block divs
Give either the first .block an additional 4% margin-left or set a padding-left of 4% on #frame
Of course, you can change these values as long as they add up to a maximum of 100% of #frame.
#frame {
width: 100%;
box-sizing: border-box;
margin: 0;
padding: 0 0 0 4%;
}
#frame div {
display: inline-block;
background-color: brown;
width: 20%;
margin: 1em 4% 1em 0;
}
<div id="frame">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
<div class="block">4</div>
</div>
</div>
Flexbox may be your best approach, but be aware that older browsers do not support it.
#frame div {
background-color: brown;
width: 20%;
text-align:center;
}
#frame {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -moz-flex;
display: -webkit-flex;
display: flex;
-webkit-justify-content: space-around;
justify-content: space-around;
}
https://jsfiddle.net/02mp1yxv/
Flex makes this easy :
#frame div {
background-color: brown;
margin: 5px;
flex: 1;
padding:1em;
color:silver
}
#frame {
display: flex;
}
<div id="frame">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
<div class="block">4</div>
</div>
For a single row table does the job too for older browsers :
#frame div {
background-color: brown;
display:table-cell;
padding:1em;
color:silver
}
#frame {
display: table;
width:100%;
border-spacing: 10px 0;;
}
<div id="frame">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
<div class="block">4</div>
</div>
or grid for latest browsers (where columns number is known:
#frame div {
background-color: brown;
padding: 1em;
color: silver
}
#frame {
display: grid;
grid-template-columns: 1fr 1fr 1fr 1fr;
grid-column-gap: 10px;
}
<div id="frame">
<div class="block">1</div>
<div class="block">2</div>
<div class="block">3</div>
<div class="block">4</div>
</div>