Position sticky with direction rtl not working - html

I have a wrapper div.container inside are div.children. I am setting position:sticky on the first child. I works fine on direction:ltr, however on direction:rtl sticky don't work.
I'm not sure if this is a browser bug or my styles are just wrong. Please note that I don't have access to the html itself, I can only change the css file and no js as possible.
Tested on:
Firefox - Pass ✅
Google Chrome - Fail ❌
Safari - Fail ❌
.container {
margin: 10px;
padding: 0;
border: 1px solid #000;
overflow-x: scroll;
overflow-y: hidden;
width: 500px;
position: relative;
white-space: nowrap;
}
.container.ltr { direction: ltr; }
.container.rtl { direction: rtl; }
.children {
display: inline-block;
margin: 0;
padding: 0;
width: 100px;
height: 100px;
border: 1px solid rgba(0,0,0,0.08);
}
.children.sticky {
position: sticky;
background: #f30;
color: #fff;
}
.container.ltr .children.sticky { left: 0; }
.container.rtl .children.sticky { right: 0; }
<div class="container ltr">
<div class="children sticky">1</div>
<div class="children">2</div>
<div class="children">3</div>
<div class="children">4</div>
<div class="children">5</div>
<div class="children">6</div>
<div class="children">7</div>
<div class="children">8</div>
<div class="children">9</div>
<div class="children">10</div>
</div>
<div class="container rtl">
<div class="children sticky">1</div>
<div class="children">2</div>
<div class="children">3</div>
<div class="children">4</div>
<div class="children">5</div>
<div class="children">6</div>
<div class="children">7</div>
<div class="children">8</div>
<div class="children">9</div>
<div class="children">10</div>
</div>
Chromium Bug Report
https://bugs.chromium.org/p/chromium/issues/detail?id=1140374

I bumped into this same issue.
Managed to find a workaround by using an extra container div, which seems to work fine on Chrome (v93), but still fails in Safari (v14.1.2), somehow it moves the sticky element to the left (???)
.container {
margin: 10px;
border: 1px solid #000;
overflow: auto;
width: 500px;
white-space: nowrap;
}
.container.ltr {
direction: ltr;
}
.container.rtl {
direction: rtl;
}
.inner {
display: inline-block;
}
.children {
display: inline-block;
width: 100px;
height: 100px;
border: 1px solid rgba(0,0,0,0.08);
}
.children.sticky {
position: sticky;
background: #f30;
color: #fff;
}
.container.ltr .children.sticky {
left: 0;
}
.container.rtl .children.sticky {
right: 0;
}
<div class="container ltr">
<div class="children sticky">1</div>
<div class="children">2</div>
<div class="children">3</div>
<div class="children">4</div>
<div class="children">5</div>
<div class="children">6</div>
<div class="children">7</div>
<div class="children">8</div>
<div class="children">9</div>
<div class="children">10</div>
</div>
<div class="container rtl">
<div class="inner">
<div class="children sticky">1</div>
<div class="children">2</div>
<div class="children">3</div>
<div class="children">4</div>
<div class="children">5</div>
<div class="children">6</div>
<div class="children">7</div>
<div class="children">8</div>
<div class="children">9</div>
<div class="children">10</div>
</div>
</div>
In my real use case there are more sticky elements (like the text in each children box), which are working somehow in Safari as well, but could not replicate that with a simple example. I also have a sticky sidebar, which has the same behavior as in the example above.

position: sticky
has got certain set of limitations in it's behaviour, please refer to https://www.designcise.com/web/tutorial/how-to-fix-issues-with-css-position-sticky-not-working
Please check if position: fixed serves your purpose.
.container {
margin: 10px;
padding: 0;
border: 1px solid #000;
overflow-x: scroll;
overflow-y: hidden;
width: 500px;
position: relative;
white-space: nowrap;
}
.container.ltr { direction: ltr; }
.container.rtl { direction: rtl; }
.children {
display: inline-block;
margin: 0;
padding: 0;
width: 100px;
height: 100px;
border: 1px solid rgba(0,0,0,0.08);
}
.container.ltr .children:nth-child(2){
margin-left: 102px;
}
.container.rtl .children:nth-child(2){
margin-right: 102px;
}
.children.sticky {
/* position: sticky; */
position :fixed;
background: #f30;
color: #fff;
}
/*.container.ltr .children.sticky { left: 0; }
.container.rtl .children.sticky { right: 0; } */
<div class="container ltr">
<div class="children sticky">1</div>
<div class="children">2</div>
<div class="children">3</div>
<div class="children">4</div>
<div class="children">5</div>
<div class="children">6</div>
<div class="children">7</div>
<div class="children">8</div>
<div class="children">9</div>
<div class="children">10</div>
</div>
<div class="container rtl">
<div class="children sticky">1</div>
<div class="children">2</div>
<div class="children">3</div>
<div class="children">4</div>
<div class="children">5</div>
<div class="children">6</div>
<div class="children">7</div>
<div class="children">8</div>
<div class="children">9</div>
<div class="children">10</div>
</div>

am also having the same issue but with table scroll with a sticky header above it & so as a temp solution for now, we can us a bit of js to reset the scroll to start from the right as expected.
so lets say we have a div that have a scrollable table and a header that should be sticky when we scroll right/left
<div class="scrollable" data-scroll-reset>
<div class="sticky">
this should remain still no matter how we scroll to left/right
</div>
<table class="rtl">
<thead>...</thead>
<tbody>...</tbody>
</table>
</div>
<style>
.scrollable {
overflow-x: scroll;
}
.sticky {
left: 0;
right: 0;
z-index: 1;
position: sticky;
}
.rtl {
direction: rtl;
}
</style>
<script>
window.addEventListener('load', () => {
document.querySelectorAll('[data-scroll-reset]').forEach((e) => {
e.scrollLeft = 10000
})
})
</script>
both data-scroll-reset & rtl should be added on condition, otherwise it will mess the scrolling when the direction is changed to ltr.

Related

How can I make an anchor element cover an entire div element?

I want when clicking anywhere on the div.parent to act as a link without including the tag in the entire div.des
I try to many times but unable to do it.
div.parent {
background-color: gray;
padding: 5px;
}
a {
width: 100px;
height: 100px;
display: block;
background-color: white
}
<div style="display: flex;justify-content: center;gap: 20px">
<div class="parent">
<div class="des">
<p>Title</p>
<i>Price</i>
</div>
</div>
<div class="parent">
<div class="des">
<p>Title</p>
<i>Price</i>
</div>
</div>
</div>
If you don't want to just wrap your div with the anchor we can learn from Bootstrap's stretched links and use an absolutely-positioned pseudo-element on the anchor.
div.parent {
background-color: gray;
padding: 5px;
position: relative;
}
a {
width: 100px;
height: 100px;
display: block;
background-color: white
}
a::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<div style="display: flex;justify-content: center;gap: 20px">
<div class="parent">
<div class="des">
<p>Title</p>
<i>Price</i>
</div>
</div>
<div class="parent">
<div class="des">
<p>Title</p>
<i>Price</i>
</div>
</div>
</div>

css position left or right does not working on ie11

position absolute left or right does not show the .box background color in Internet Explorer 11 (IE11) at the same time all the other browsers are working fine (Please find attached screenshots)
Unfortunately I can't put the width. because the number of images may vary
Demo: https://codepen.io/anon/pen/qVLyaM
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.wrap {
display: block;
padding: 1rem;
border: 1px solid black;
background-color: deepskyblue;
width: 700px;
height: 300px;
position: relative;
}
.box {
display: inline-flex;
background-color: tomato;
padding: 1rem;
position: absolute;
left: 0;
left: 100%;
bottom: 100%;
}
<div class="wrap">
<div class="box">
<div class="box-img"><img src="http://via.placeholder.com/100x100?text=Logo 01"></div>
<div class="box-img"><img src="http://via.placeholder.com/100x100?text=Logo 01"></div>
<div class="box-img"><img src="http://via.placeholder.com/100x100?text=Logo 01"></div>
<div class="box-img"><img src="http://via.placeholder.com/100x100?text=Logo 01"></div>
<div class="box-img"><img src="http://via.placeholder.com/100x100?text=Logo 01"></div>
<div class="box-img"><img src="http://via.placeholder.com/100x100?text=Logo 01"></div>
<div class="box-img"><img src="http://via.placeholder.com/100x100?text=Logo 01"></div>
</div>
</div>

Arrange horizontal div inside parent div

I would like achieve what is shown in the image below, meant to select colors using CSS3.
The code is currently here.
.colors {
background: white;
width: 80%;
height: 10%;
position: absolute;
top: 60%;
display: inline-block;
overflow-x: scroll;
white-space: no-wrap;
}
.select {
float: left;
margin: 10px;
color: transparent;
z-index: 22;
background: red;
width: 20%;
}
<div class="colors">
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"> </div>
</div>
The divs I made aren't showing up. What can I do to solve this?
Your div aren't showing because you didn't set any height to them. You have also a syntax error here white-space: no-wrap as it should be white-space: nowrap.
By the way, you can simply use flex instead of floating elements. When using flex you are not obliged to specify the height of the element :
.colors {
background: white;
width: 80%;
height: 100px;
margin: auto;
display: flex;
flex-wrap: nowrap; /* this is not mandatory as it's the default value*/
overflow-x: scroll;
border: 1px solid;
}
.select {
margin: 10px;
color: transparent;
background: red;
flex: 0 0 20%;
}
<div class="colors">
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"> </div>
</div>
Or inline-block solution. But here you need to specify the height and pay attention to overflow :
.colors {
background: white;
width: 80%;
height: 100px;
margin: auto;
overflow-x: scroll;
border: 1px solid;
white-space:nowrap;
}
.select {
margin: 10px;
color: transparent;
background: red;
display:inline-block;
height:calc(100% - 24px); /* You need to remove both margin and height of scroll*/
width:20%;
}
<div class="colors">
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"> </div>
</div>
Remove the float:left method from selection class. Try like this.
.colors {
background: black;
width: 80%;
height: 20%;
position: absolute;
top: 60%;
overflow: auto;
white-space: nowrap;
}
.select {
margin: 10px;
color: transparent;
z-index: 22;
background: red;
width: 20%;
height: 80%;
display:inline-block;
}
<!DOCTYPE html>
<html>
<body>
<div class="colors">
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"></div>
<div class="select"> </div>
</div>
</body>
</html>

How to align a list of elements to bottom?

I'd like to align a list of elements inside of a container to bottom. By default it sticks to the top of the container.
Note that this list needs to keep its scroll ability. So I can't use flex. Flex makes elements resize and avoids scroll.
I can't think of an easy way to do this.
JSFiddle
#list {
height: 200px;
}
.item {
height: 30px;
line-height: 30px;
background-color: lightgray;
margin: 3px 0;
}
<div id="list">
<div class="item">Item0</div>
<div class="item">Item1</div>
<div class="item">Item2</div>
<div class="item">Item3</div>
<div class="item">Item4</div>
<div class="item">Item5</div>
<div class="item">Item6</div>
<div class="item">Item7</div>
<div class="item">Item8</div>
<div class="item">Item9</div>
</div>
There is a hack using transform scaling in the y-direction - see demo below:
#list {
height: 200px;
border:1px solid green;
overflow-y: auto;
transform: scaleY(-1);
}
.item {
height: 30px;
line-height: 30px;
background-color: lightgray;
margin: 3px 0;
transform: scaleY(-1);
}
<div id="list">
<div class="item">Item0</div>
<div class="item">Item1</div>
<div class="item">Item2</div>
<div class="item">Item3</div>
<div class="item">Item4</div>
<div class="item">Item5</div>
<div class="item">Item6</div>
<div class="item">Item7</div>
<div class="item">Item8</div>
<div class="item">Item9</div>
</div>
#list {
position: absolute; bottom: 0;
}
make sure to add position: relative; to the above element
https://jsfiddle.net/ege89t3h/

Why I can not scroll on my overlay?

When I scroll on screen, everything is good.
When I click on my button, there is a overlay show up.
However, I can still scroll the div under my overlay, what i want is only to scroll my overlay.
$('#addCustomerBtn').on('click', function() {
// window.location.href = "http://dev.rabbijet.com/crm/create.html";
var modal = document.getElementById('myModal');
modal.style.display = "block";
})
body {
overflow: auto;
}
.black {
height: 200px;
width: 800px;
background-color: black;
}
.gray {
height: 200px;
width: 800px;
background-color: gray;
}
.green {
height: 700px;
background-color: green;
}
.yellow {
height: 700px;
background-color: yellow;
}
#addCustomerBtn {
font-size: 14px;
width: 120px;
border: 1px solid #20ACB3;
background-color: #20ACB3;
}
#myModal {
display: none;
position: fixed;
/* Stay in place */
z-index: 999;
/* Sit on top */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
background-color: rgba(0, 0, 0, 0.4);
}
#create-form {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
background-color: #000;
width: 500px;
height: 1500px;
background-color: red;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="btn btn-primary" id="addCustomerBtn">Click</div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
</div>
<div id="myModal">
<div id="create-form">
<div class="green"></div>
<div class="yellow"></div>
</div>
</div>
Add overflow-y: scroll; to your modal class in the CSS.
$('#addCustomerBtn').on('click', function() {
// window.location.href = "http://dev.rabbijet.com/crm/create.html";
var modal = document.getElementById('myModal');
modal.style.display = "block";
})
body {
overflow: auto;
}
.black {
height: 200px;
width: 800px;
background-color: black;
}
.gray {
height: 200px;
width: 800px;
background-color: gray;
}
.green {
height: 700px;
background-color: green;
}
.yellow {
height: 700px;
background-color: yellow;
}
#addCustomerBtn {
font-size: 14px;
width: 120px;
border: 1px solid #20ACB3;
background-color: #20ACB3;
}
#myModal {
display: none;
position: fixed;
overflow-y: scroll;
/* Stay in place */
z-index: 999;
/* Sit on top */
left: 0;
top: 0;
width: 100%;
/* Full width */
height: 100%;
/* Full height */
background-color: rgba(0, 0, 0, 0.4);
}
#create-form {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
background-color: #000;
width: 500px;
height: 1500px;
background-color: red;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="btn btn-primary" id="addCustomerBtn">Click</div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
</div>
<div id="myModal">
<div id="create-form">
<div class="green"></div>
<div class="yellow"></div>
</div>
</div>
This answer is very rough, but basically what you do is allow overflow on the modal container, and when the button is clicked you disallow overflow on the parent container. When you close the modal, remember to remove the .overflow-hidden class I made from the document body. Also, if you are using jQuery use it. It is popular because it makes many things, like applying styles, easier.
$('#addCustomerBtn').on('click', function() {
// window.location.href = "http://dev.rabbijet.com/crm/create.html";
var modal = $('#myModal');
modal.css('display','block');
$(document.body).toggleClass('overflow-hidden');
})
body {
overflow: auto;
}
.overflow-hidden {
overflow: none;
}
.black {
height: 200px;
width: 800px;
background-color: black;
}
.gray {
height: 200px;
width: 800px;
background-color: gray;
}
.green {
height: 700px;
background-color: green;
}
.yellow {
height: 700px;
background-color: yellow;
}
#addCustomerBtn {
font-size: 14px;
width: 120px;
border: 1px solid #20ACB3;
background-color: #20ACB3;
}
#myModal {
display: none;
position: absolute;
/* Stay in place */
z-index: 999;
/* Sit on top */
left: 0;
top: 0;
bottom: 0;
/* Full width */
right: 0;
/* Full height */
background-color: rgba(0, 0, 0, 0.4);
overflow: auto;
}
#create-form {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
background-color: #000;
width: 500px;
height: 1500px;
background-color: red;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="btn btn-primary" id="addCustomerBtn">Click</div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
<div class="black"></div>
<div class="gray"></div>
</div>
<div id="myModal">
<div class="close-button">X</div>
<div id="create-form">
<div class="green"></div>
<div class="yellow"></div>
</div>
</div>