I'm trying to apply a gradient mask on the right side of a horizontal scrollbar to indicate that the list scrolls horizontally. I've created a gradient-layer as my mask, however the mask moves horizontally with the navigation items when scrolled. I want the mask to stay fixed as the user scrolls through the navigation, but don't want to position it 'fixed' because I need the mask to be contained within the width and height of the navigation container. But I'm not sure how to achieve this effect. Thanks for the help!
.navigation{
display: flex;
flex-wrap: no-wrap;
overflow-x: auto;
background-color: black;
white-space: nowrap;
position: relative;
width: 100%;
}
.navigation::after {
content: "";
position: absolute;
height: 100%;
right: 0;
background-image: linear-gradient(to right, rgba(255,255,255,0), red 85%);
width: 15%;
}
.item {
flex: 0 0 auto;
height: 100px;
width: 100px;
background-color: blue;
margin-right: 10px;
}
}
<div class = "navigation">
<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 class="item"></div>
</div>
Use position:sticky
.navigation {
display: flex;
flex-wrap: no-wrap;
overflow-x: auto;
background-color: black;
white-space: nowrap;
margin:0 20px;
}
.navigation::after {
content: "";
display:block;
position: sticky;
right: 0;
background-image: linear-gradient(to right, rgba(255, 255, 255, 0), red 85%);
width: 15%;
margin-left:-15%; /* same a width to not take any space */
flex-shrink:0; /* this is important to keep the width:15% */
}
.item {
flex: 0 0 auto;
height: 100px;
width: 100px;
background-color: blue;
margin-right: 10px;
}
.navigation .item:last-child {
margin-right:auto;
}
<div class="navigation">
<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 class="item"></div>
</div>
Why not just use position: fixed while applying the same height the .item class has?
.navigation {
display: flex;
flex-wrap: no-wrap;
overflow-x: auto;
background-color: black;
white-space: nowrap;
position: relative;
width: 100%;
}
.navigation::after {
content: "";
position: fixed;
height: 100px;
right: 0;
background-image: linear-gradient(to right, rgba(255, 255, 255, 0), red 85%);
width: 15%;
}
.item {
flex: 0 0 auto;
height: 100px;
width: 100px;
background-color: blue;
margin-right: 10px;
}
<div class="navigation">
<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 class="item"></div>
</div>
Related
I want to make equal gap for the children of flexbox. I used margin-right zero for each child, then applied the margin right back on the last child. But the margin right somehow doesn't applied. You can see after you scrolled to the end of the child.
see demo below
.flex {
display: flex;
background: pink;
width: 80px;
overflow: auto;
}
.item {
min-width: 20px;
height: 20px;
background: black;
margin: 8px;
margin-right: 0;
}
.item:last-child {
margin-right: 4px;
}
<div class="flex">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
add another parent div and give overflow for parent div. For .flex class apply display:inline-flex; then it will works
.flex-parent{
overflow: auto;
width: 80px;
}
.flex {
display: flex;
background: pink;
min-width:100%;
float:left;
}
.flex-parent{
overflow: auto;
width: 80px;
}
.flex {
display: inline-flex;
background: pink;
/*min-width:100%;
float:left;*/
}
.item {
min-width: 20px;
height: 20px;
background: black;
margin: 8px;
margin-right: 0;
}
.item:last-child {
margin-right: 4px;
}
<div class="flex-parent">
<div class="flex">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div>
.flex {
display: flex;
background: pink;
width: 200px;
overflow: auto;
justify-content: space-between;
}
.item {
min-width: 20px;
height: 20px;
background: black;
}
<div class="flex">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
This question already has answers here:
CSS-only masonry layout
(4 answers)
Closed 4 years ago.
Hello! Can you help me? I'm trying to do two column layout with same spacing between items in same column.
.flex {
margin: 0;
padding-left: 0;
list-style: none;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
align-content: center;
}
.item {
width: 45%;
height: 200px;
margin-bottom: 10px;
background-color: navy;
}
.item:nth-child(1) {
height: 210px;
}
.item:nth-child(2) {
height: 500px;
}
.item:nth-child(3) {
height: 360px;
}
.item:nth-child(4) {
height: 400px;
}
.item:nth-child(5) {
height: 150px;
}
<div class="flex">
<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>
Thanks for every good advice & your help!
You could use column-count instead of flexbox. In this situation, there's no need to implement a flexible box layout. You're not trying to maintain identical sizes or adjust for any odd alignment.
.flex
{
margin: 0;
padding-left: 0;
list-style: none;
column-count: 2;
column-gap: 10px;
}
.item{
height: 200px;
margin-bottom: 10px;
background-color: navy;
break-inside: avoid;
}
.item:nth-child(1){height: 210px;}
.item:nth-child(2){height: 500px;}
.item:nth-child(3){height: 360px;}
.item:nth-child(4){height: 400px;}
.item:nth-child(5){height: 150px;}
<div class="flex">
<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>
Here's a way to use percentages for the column gap. It uses 0px column-gap and a negative margin on the container to adjust for the excess margins on the left and right.
.flex
{
margin: 0;
padding-left: 0;
list-style: none;
column-count: 2;
column-gap: 0;
margin: 0 -1.25%;
}
.item{
height: 200px;
margin-bottom: 10px;
background-color: navy;
break-inside: avoid;
margin: 0 2.5% 5%;
}
.item:nth-child(1){height: 210px;}
.item:nth-child(2){height: 500px;}
.item:nth-child(3){height: 360px;}
.item:nth-child(4){height: 400px;}
.item:nth-child(5){height: 150px;}
<div class="flex">
<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>
In the example provided, the horizontal scroll container scrolls left and right as it should, while the vertical scroll container expands the page off the screen while not allowing for any scrolling. The scroll bar appears, but it is disabled.
The idea is to have the Vertical scroll container cover the remainder of the screen after the Horizontal scroll container.
Considering the Horizontal container is 40px high in this example, I set the max-height to the vertical container as calc(100% - 40px)
#container-scroll-horiz
{
width: 100%;
height: 40px;
overflow-x: scroll;
overflow-y: hidden;
white-space: nowrap;
border: 1px solid blue;
}
#container-scroll-horiz .item
{
display: inline-block;
width: 20vw;
height: 50px;
border: 1px solid black;
}
#container-scroll-vert
{
width: 100%;
max-height: calc(100% - 40px);
overflow-x: hidden;
overflow-y: scroll;
border: 1px solid red;
}
#container-scroll-vert .item
{
width: 100%;
height: 20vh;
border: 1px solid purple;
}
<div id="container-scroll-horiz">
<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 id="container-scroll-vert">
<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 class="item"></div>
<div class="item"></div>
</div>
Because the vertical scroll's element has nothing to set its 100% height against.
When using percent on an element's height, its parent need a fixed height.
If all parents use percent, it need to be passed on all the way up to the body, which will use the viewport's fixed height.
You can either
use viewport units, max-height: calc(100vh - 40px); (sample 1)
set a height on the body, html, body { height: 100%; } (sample 2)
Sample 1
html, body {
margin: 0;
}
#container-scroll-horiz
{
width: 100%;
height: 40px;
overflow-x: scroll;
overflow-y: hidden;
white-space: nowrap;
border: 1px solid blue;
box-sizing: border-box;
}
#container-scroll-horiz .item
{
display: inline-block;
width: 20vw;
height: 50px;
border: 1px solid black;
}
#container-scroll-vert
{
width: 100%;
max-height: calc(100vh - 40px);
overflow-x: hidden;
overflow-y: scroll;
border: 1px solid red;
box-sizing: border-box;
}
#container-scroll-vert .item
{
width: 100%;
height: 20vh;
border: 1px solid purple;
}
<div id="container-scroll-horiz">
<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 id="container-scroll-vert">
<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 class="item"></div>
<div class="item"></div>
</div>
Sample 2
html, body {
margin: 0;
height: 100%;
}
#container-scroll-horiz
{
width: 100%;
height: 40px;
overflow-x: scroll;
overflow-y: hidden;
white-space: nowrap;
border: 1px solid blue;
box-sizing: border-box;
}
#container-scroll-horiz .item
{
display: inline-block;
width: 20vw;
height: 50px;
border: 1px solid black;
}
#container-scroll-vert
{
width: 100%;
max-height: calc(100% - 40px);
overflow-x: hidden;
overflow-y: scroll;
border: 1px solid red;
box-sizing: border-box;
}
#container-scroll-vert .item
{
width: 100%;
height: 20vh;
border: 1px solid purple;
}
<div id="container-scroll-horiz">
<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 id="container-scroll-vert">
<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 class="item"></div>
<div class="item"></div>
</div>
It is because use 100% in setting max-height of the vertical container, it will expand combining its children's height since the vertical container doesn't have anything to reference its height from. you can use 100vh instead this way it will use viewport height limiting the max height viewable to window. Check my answer if this is what your trying to implement on your code. Goodluck
#container-scroll-horiz
{
width: 100%;
height: 40px;
overflow-x: scroll;
overflow-y: hidden;
white-space: nowrap;
border: 1px solid blue;
}
#container-scroll-horiz .item
{
display: inline-block;
width: 20vw;
height: 50px;
border: 1px solid black;
}
#container-scroll-vert
{
width: 100%;
overflow-x: hidden;
overflow-y: scroll;
border: 1px solid red;
max-height : calc(100vh - 60px); /* 40px plus 20px for horizontal scrollbar */
}
#container-scroll-vert .item
{
width: 100%;
height: 20vh;
border: 1px solid purple;
}
<div id="container-scroll-horiz">
<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 id="container-scroll-vert">
<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 class="item"></div>
<div class="item"></div>
</div>
Html:
<div id="container-scroll-horiz">
<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 id="container-scroll-vert">
<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 class="item"></div>
<div class="item"></div>
</div>
Css:
html, body {
margin: 0;
height: 100%;
}
#container-scroll-horiz {
width: 100%;
height: 40px;
overflow-x: scroll;
overflow-y: hidden;
white-space: nowrap;
border: 1px solid blue;
box-sizing: border-box;
}
#container-scroll-horiz .item {
display: inline-block;
width: 20vw;
height: 50px;
border: 1px solid black;
}
#container-scroll-vert {
width: 100%;
max-height: calc(100% - 40px);
overflow-x: hidden;
overflow-y: scroll;
border: 1px solid red;
box-sizing: border-box;
}
#container-scroll-vert .item {
width: 100%;
height: 20vh;
border: 1px solid purple;
}
I want to vertically align the items to the bottom of the container. The difficulty is coming from the fact that .container is floated left, I didn't find a solution so far.
.container {
width: 40px;
height: 250px;
background: #aaa;
float: left; /* cannot be removed */
}
.item {
width: 40px;
height: 40px;
background: red;
border-radius: 50%;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
If you always have 4 items and everything has a fixed height, you can simply do the math and set some top margin on the first item:
.item:first-child {
margin-top: 90px; /* 250-40x40 */
}
You can also use flexbox:
.container {
width: 40px;
height: 250px;
background: #aaa;
float: left;
/* new */
display: flex;
flex-direction: column;
justify-content: flex-end;
}
.item {
width: 40px;
height: 40px;
background: red;
border-radius: 50%;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
I have the following requirement.
The green colored parent width will be varying depending on device width. I need all the boxes to be in the center of the parent.
I have tried the following things already, but it didnt help me.
Trial 1
Parent {text-align:center} box {display:inline-block}.
This resulted in following output
Trial 2
Parent {text-align:center} box{float:left}.
This resulted in following output
Trial 3
Parent {display:flex} box -> justify-around & justify-between also didn't work.
.parent {
text-align: center;
}
.item {
display: inline-block;
width: 100px;
height: 100px;
background: red;
}
<div class="parent">
<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 class="item"></div>
</div>
Any help on this will be appreciated.
Without Javascript this very hard using floats &/or inline-block.
Flexbox offers some hope but even then some creativity is required.
Essentially, provided the maximum number of elements "per row" is known you can create a required number of invisible elements which can be ustilised in conjunction with justify-content:center to acheieve the last line appearance you require by essentially pushing the last line content back over to the left.
Codepen Demo
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.parent {
text-align: center;
border: 1px solid grey;
width: 80%;
max-width: 800px;
margin: 1em auto;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.item {
width: 100px;
height: 100px;
margin: 10px;
background: red;
}
.balancer {
height: 0;
width: 100px;
margin: 0 10px;
visibility: hidden;
}
<div class="parent">
<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 class="item"></div>
<div class="balancer"></div>
<div class="balancer"></div>
<div class="balancer"></div>
<div class="balancer"></div>
</div>
Got it working by using jQuery and adding a #wrapper.
All you've got to do is calculate how many items will fit on one row. Then you set the wrapper to the exact width that is needed to fit these items.
I hoped it could be done in pure CSS, but as far as I know there is no Math.floor() equivalent for CSS.
Example:
function fitItemsOnRow() {
var windowWidth = $(window).width();
var itemWidth = $(".item").outerWidth(true);
var itemAmount = Math.floor((windowWidth / itemWidth));
if(itemAmount > $(".item").length) {
/* Set the maximum amount of items */
itemAmount = $(".item").length;
}
var rowWidth = itemWidth * itemAmount;
$("#wrapper").width(rowWidth);
}
$(window).resize(function() {
/* Responsive */
fitItemsOnRow();
});
$(document).ready(function() {
fitItemsOnRow();
});
body {
margin: 0px;
}
#parent {
background: #75DB3C;
min-width: 100vw;
min-height: 100vh;
text-align: center;
}
#wrapper {
display: inline-block;
text-align: left;
font-size: 0px; /* Removes default margin */
}
.item {
display: inline-block;
margin: 12px;
width: 100px;
height: 100px;
background: #0B56A9;
}
<div id="parent">
<div id="wrapper">
<!-- A wrapper is necessary to center the 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>
</div>
<!-- jQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
You can do this with css selector "nth-of-type(n)"
<div class="parent">
<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 class="item"></div>
</div>
and css here
.parent
{
display: block;
width: 980px;
padding: 10px 50px;
background: green;
box-sizing: border-box;
}
.parent::after
{
content: '';
display: block;
clear: both;
}
.item
{
float: left;
width: 24%;
margin-right: 1.25%;
margin-bottom: 1.25%;
/*
note
you may need min height , height or overflow:hidden
*/
}
.item:nth-of-type(4n)
{
float: right;
margin-right: 0;
}