I use flexbox and my flex items can be collapsed. If I use 'align-items: stretch', they won't be able to collapse. If I use 'flex-start', there is a lot of empty space. The problem is I don't know what to do with empty space when it's not collapsed. Is it possible to set the height of elements like the I use 'stretch'?
If not, what are the alternatives?
The logic looks like this: https://codepen.io/darius9171/pen/qyVERX
or:
document.querySelectorAll('.item').forEach(item => {
item.addEventListener('click', (event) => {
event.currentTarget.classList.toggle('collapsed');
});
})
.container {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
border: 1px solid black;
width: 100%;
}
.container .item {
flex-basis: calc(100% / 3 - 1rem);
flex-grow: 1;
width: 50px;
background-color: black;
margin: 0.5rem;
color: white;
text-align: center;
cursor: pointer;
}
.container .item:nth-child(1) .body {
height: 25px;
}
.container .item:nth-child(2) .body {
height: 50px;
}
.container .item:nth-child(3) .body {
height: 75px;
}
.container .item:nth-child(4) .body {
height: 100px;
}
.container .item:nth-child(5) .body {
height: 125px;
}
.container .item .body {
transition: all 0.7s ease-in-out;
overflow: hidden;
}
.container .item.collapsed .body {
height: 0;
}
<div class="container">
<div class="item">
<div class="header">Head 1</div>
<div class="body">Body 1</div>
</div>
<div class="item">
<div class="header">Head 2</div>
<div class="body">Body 2</div>
</div>
<div class="item">
<div class="header">Head 3</div>
<div class="body">Body 3</div>
</div>
<div class="item">
<div class="header">Head 4</div>
<div class="body">Body 4</div>
</div>
<div class="item">
<div class="header">Head 5</div>
<div class="body">Body 5</div>
</div>
</div>
Related
This question already has answers here:
How does flex-wrap work with align-self, align-items and align-content?
(2 answers)
Closed 2 days ago.
I've a div container (the grey one), with contains some children with a flex display. The container can scroll vertically.
The height of the gray container should be the same as the window.
.container {
width: 500px;
height: 100vh;
background-color: lightgrey;
padding: 10px;
overflow: auto;
display: flex;
flex-wrap: wrap;
}
.item {
width: 200px;
height: 200px;
background-color: gold;
border: 1px solid orange;
}
<div class="container">
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
</div>
If you run the snippet, you can see the result: each item is near another item and the container scrolls.
The problem is that if I remove some items (their number is dynamic), there is extra space between items. Why?
I don't want this extra space, how can I "remove" it?
When using flex-wrap: wrap, the contents are grouped into "lines" of contents known as flex lines, the align-content property controls how the flex lines are packed. In your case, setting align-content: flex-start; would achieve your needs.
Source W3C
.container {
width: 500px;
height: 100vh;
background-color: lightgrey;
padding: 10px;
overflow: auto;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
.item {
width: 200px;
height: 200px;
background-color: gold;
border: 1px solid orange;
}
<div class="container">
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
</div>
Credit: This answer is inspired by another Stack Overflow post How does flex-wrap work with align-self,align-items and align-content
Because container height is 100vh. if you update it like height:auto, this issue will be fixed. Or items list should be wrapped by another element like below code. it's working
.container {
width: 500px;
height: 100vh;
background-color: lightgrey;
padding: 10px;
overflow: auto;
}
.items {
display: flex;
flex-wrap: wrap;
}
.item {
width: 200px;
height: 200px;
background-color: gold;
border: 1px solid orange;
}
<div class="container">
<div class="items">
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
<div class="item" ></div>
</div>
</div>
I'm trying to build a horizontal scroll with multiple content boxes that belong to one title. So I'd like the title to stay while the content scrolls past it, until the next section with a new title comes.
Here's what I was trying to do: https://jsfiddle.net/kjo4duts/23/
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.scroll {
display: flex;
flex-direction: row;
width: 100vw;
height: 100px;
background: yellow;
overflow: scroll;
}
.item {
flex-shrink: 0;
width: 200px;
height: 100%;
margin-right: 20px;
}
.scroll .item .title {
position: sticky;
left: 0;
top: 0;
width: 100%;
height: 40px;
}
.item .content {
width: 100%;
height: 60px;
border: 3px solid green;
}
<div class="scroll">
<div class="item">
<div class="title">
Title 1
</div>
<div class="content">
Content
</div>
</div>
<div class="item">
<div class="title">
</div>
<div class="content">
Content
</div>
</div>
<div class="item">
<div class="title">
Title 2
</div>
<div class="content">
Content
</div>
</div>
<div class="item">
<div class="title">
</div>
<div class="content">
Content
</div>
</div>
<div class="item">
<div class="title">
</div>
<div class="content">
Content
</div>
</div>
</div>
Is there a way to address the "position: sticky" property to the outer parent (.scroll)? Or is there a smooth way to do it in JavaScript?
I tried to change the HTML structure, but with Flexbox you need a container for each box to get a horizontal layout..
Thanks in advance!
Edit: For anyone with the same problem. The solution is to add a relative position to the outer parent and the change the HTML structure a bit.
See updated Fiddle: https://jsfiddle.net/r2czqwn7/20/
Parent (.scroll) has to be position: relative at first as you can check below but I would consider different structure (all contents with same title could be in same div) to stick it over multiple items.
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
}
.scroll {
position: relative;
display: flex;
flex-direction: row;
width: 100vw;
height: 100px;
background: yellow;
overflow: scroll;
}
.item {
flex-flow: column;
flex-shrink: 0;
width: 200px;
height: 100%;
margin-right: 20px;
}
.scroll .item .title {
position: sticky;
display: inline;
left: 0;
top: 0;
width: 100%;
height: 40px;
}
.item .content {
width: 100%;
height: 60px;
border: 3px solid green;
}
.item .content:first-child {
margin-top: 1rem;
}
<div class="scroll">
<div class="item">
<div class="title">
Title 1
</div>
<div class="content">
Content
</div>
</div>
<div class="item">
<div class="content">
Content
</div>
</div>
<div class="item">
<div class="title">
Title 2
</div>
<div class="content">
Content
</div>
</div>
<div class="item">
<div class="content">
Content
</div>
</div>
<div class="item">
<div class="content">
Content
</div>
</div>
</div>
I want to have a similar effect like on this page: https://melaniedaveid.com/ (half of the page is scrollable).
I can make a sticky box, but there are certain things that I don't know how to make, such as the text. The text must be bigger than the box, but if overflow: hidden, then it is not scrollable. If it's overflow: scroll, it scrolls only if the mouse is hovering over the section, but I want the mouse to be able to scroll anywhere on the page.
body {
display: flex;
}
.example {
width: 50%;
}
.block {
background: #888888;
height: 300px;
/* margin: 1em; */
border: 1px solid black;
}
.block.one {
height: 100px;
}
.box {
width: 100%;
height: 100px;
background: orange;
display: flex;
justify-content: center;
align-items: center;
font-size: 2em;
}
.sticky {
position: sticky;
top: 10px;
}
.orange{
background: orange;
}
<div class="example">
<div class="block one"></div>
<div class="block">
<p class="box sticky"> </p>
</div>
<div class="block"></div>
</div>
<div class="example">
<div class="block one"></div>
<div class="block orange"></div>
<div class="block"></div>
</div>
Is this how you want it?
To create the sticky effect use position: sticky.
Code:
#wrapper {
display:flex;
flex-direction:row;
}
#sticky {
position: sticky;
position: -webkit-sticky;
background: #f83d23;
width: 50%;
height: 300px;
top: 0;
display: flex;
justify-content: center;
align-items: center;
box-shadow: 0 0 6px #000;
color: #fff;
}
#para{
width:50%;
margin:10px;
}
<div id="wrapper">
<div id="sticky">
sticky
</div>
<div id="para">
This is a para
</div>
</div>
In the snippet provided, I have 3 sections: The first contains a single image, the second has two images, and the last one has no images.
I would like for the .image class within the first section to be 100% in width only if there is no other .image div present.
However, once there is another .image div present, (as shown in the second section), I would like it to default back to 50% width.
How should I execute this?
$(function() {
$('.container > .section').each(function() {
if (!$(this).find(".image").length) {
$(this).before('<div class="noimage">No images to display.</div>');
}
});
});
body {
font-size: 16px;
margin: 0;
padding: 0;
border: 0;
}
h1 {
font-size: 22px;
margin-top: 0;
margin-bottom: 10px;
}
.container {
box-sizing: border-box;
overflow: auto;
}
.image {
float: left;
display: block;
width: 50%;
line-height: 0;
}
.image img {
width: 100%;
height: auto;
}
.container {
margin: 0 auto;
max-width: 300px;
border: 1px solid lightgrey;
padding: 10px;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- 1 Image -->
<div class="container">
<h1>Section With 1 Image:</h1>
<div class="section">
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/pear-flat.png"></div>
</div>
</div>
<!-- 2 Images -->
<div class="container">
<h1>Section With 2 Images:</h1>
<div class="section">
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/ice-cream-cone-flat.png"></div>
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/orange-flat.png"></div>
</div>
</div>
<!-- No Images -->
<div class="container">
<h1>Section With No Images:</h1>
<div class="section"></div>
</div>
You could display the section as a table and the div.image as a table-cell. Then the image would resize according to the number of "cell's" (div.image's) present.
div.container{
display: 100%;
}
div.section{
width: 100%;
display: table;
}
div.section div.image{
display: table-cell;
}
div.section div.image img{
width: 100%;
height: auto;
}
Here's a JSFiddle:
https://jsfiddle.net/ColiniloC/Lnnkpx6L/
Figured out a simpler solution with flexbox:
$(function() {
$('.container > .section').each(function() {
if (!$(this).find(".image").length) {
$(this).before('<div class="noimage">No images to display.</div>');
}
});
});
body {
font-size: 16px;
margin: 0;
padding: 0;
border: 0;
}
h1 {
font-size: 22px;
margin-top: 0;
margin-bottom: 10px;
}
.container {
box-sizing: border-box;
margin: 0 auto;
max-width: 300px;
border: 1px solid lightgrey;
padding: 10px;
display: block;
}
.section {
display: flex;
flex-wrap: wrap;
overflow: hidden;
align-items: center;
margin: 0 -5px;
}
.image {
flex: 1 1 50%;
line-height: 0;
width: 100%;
padding: 0 5px;
box-sizing: border-box;
}
.container .image:nth-of-type(n+3) {
padding-top: 10px;
}
.image img {
width: 100%;
height: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!-- 1 Image -->
<div class="container">
<h1>Section With 1 Image:</h1>
<div class="section">
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/pear-flat.png"></div>
</div>
</div>
<!-- 2 Images -->
<div class="container">
<h1>Section With 2 Images:</h1>
<div class="section">
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/pear-flat.png"></div>
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/ice-cream-cone-flat.png"></div>
</div>
</div>
<!-- 4 Images -->
<div class="container">
<h1>Section With 4 Images:</h1>
<div class="section">
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/pear-flat.png"></div>
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/ice-cream-cone-flat.png"></div>
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/orange-flat.png"></div>
<div class="image"><img src="https://freeiconshop.com/wp-content/uploads/edd/burger-flat.png"></div>
</div>
</div>
<!-- No Images -->
<div class="container">
<h1>Section With No Images:</h1>
<div class="section"></div>
</div>
I am trying to make simple css layout. I want 3 box
{Left} {center} {right}
So I write this code
#myleft {
position: relative;
float: left;
width: 20%;
background-color: #CC6600;
}
#mycenter {
width: 60%;
background-color: #f2f4f4;
}
* html #mycenter {
height: 1%
}
#myright {
position: relative;
float: right;
width: 20%;
background-color: #FF6633;
}
<div id='left'> Left </div>
<div id='mycenter'> Center </div>
<div id='right'> right </div>
but instead of
{left} {center} {right}
{left}
{center}
{right}
I don't know why but it goes like this even the float is left and right
You didn't name your div id's correctly. they should be myleft and myright
body {
width: 100%;
}
#myleft {
position:relative;
float:left;
width:20%;
background-color:#CC6600;
}
#mycenter {
width:60%;
float: left;
background-color:#f2f4f4;
}
#mycenter {
height:1%
}
#myright {
float:left;
width:20%;
background-color:#FF6633;
}
<div id='myleft'> Left </div>
<div id='mycenter'> Center </div>
<div id='myright'> right </div>
Wrap your divs into a main div and try to use Flexbox
Stack Snippet
.d-flex {
display: flex;
flex-wrap: wrap;
}
#myleft {
position: relative;
width: 20%;
background-color: cyan;
}
#mycenter {
width: 60%;
background-color: #f2f4f4;
}
#myright {
position: relative;
width: 20%;
background-color: cyan;
}
<div class="d-flex">
<div id='myleft'> Left </div>
<div id='mycenter'> Center </div>
<div id='myright'> right </div>
</div>
And, of course, there is grid. First wrap the "gridded" elements
<div id='wrapper'>
<div id='left'> Left </div>
<div id='center'> Center </div>
<div id='right'> right </div>
</div>
#wrapper {
display: grid;
grid-template-columns: 2fr 6fr 2fr;
}
Then, optionally, if you want the content of each sub-div to be centered:
#left, #right, #center {
margin-left:auto;
margin-right:auto;
}
.container {
display: flex;
}
.box1 {
flex: 1 ;
text-align: center;
background-color: gray;
}
.box2 {
flex: 2;
text-align: center
}
.box3 {
flex: 1;
text-align: center;
background-color: gray;
}
<div class="container">
<div class="box1">
<p> text</p>
</div>
<div class="box2">
<p> text</p>
</div>
<div class="box3">
<p> text</p>
</div>
</div>