let modal = document.querySelector('.modal');
let items = document.querySelectorAll('.item');
items.forEach(fe);
function fe(item, index){
item.addEventListener("click", function(){
item.querySelector('.modal').classList.toggle('show');
});
}
.horizontal-scrollable{
display: flex;
flex-direction: column;
padding: 10px;
background-color: #d2d2d2;
overflow-x:auto;
max-width: 450px;
}
.item {
background-color: #a29f9b;
margin: 5px;
padding: 0 5px;
cursor:pointer;
position:relative;
}
.item2{
min-width:500px
}
.item3{
min-width:700px
}
.modal{
display:none;
position: absolute;
top: 100%;
right: 0;
background: #4977d0;
z-index: 100;
}
.modal.show{
display:block;
}
<div class="horizontal-scrollable">
<div class="item item1">
<h1>Item 1</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item2">
<h1>Item 2</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item3">
<h1>Item 3</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item4">
<h1>Item 4</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
</div>
In the above code snippet, If you click on any item, then it will show a modal on the right side. As you can see, item 3 is larger in width. So if you click on item 3 then you have to scroll-right to view the modal.
So I want to show modal on mouse click position.
How can I do this?
There are at least two options
The first one will spawn the modal directly at the mouse position using JS
And the second one will spawn the modal on the left side. This can be achieved using CSS
First option
So basically you can get the mouse position and set the modal position to it.
In detail remove the top/left/right/bottom properties from the modal class in CSS (they aren't needed) and add some lines of JS.
Please write me in the comments if you want to align the modal a bit around the mouse cursor... It's just about a few numbers.
let modal = document.querySelector('.modal');
let items = document.querySelectorAll('.item');
items.forEach(fe);
var mousePos = {};
function fe(item, index){
item.addEventListener("click", function(e){
var rect = e.target.getBoundingClientRect(); // get some poition, scale,... properties of the item
mousePos.x = e.clientX - rect.left; // get the mouse position relative to the element
mousePos.y = e.clientY - rect.top;
item.querySelector('.modal').classList.toggle('show');
item.querySelector('.modal').style.left = mousePos.x + "px"; // set the modal position to the last stored position
item.querySelector('.modal').style.top = mousePos.y + "px";
});
}
.horizontal-scrollable{
display: flex;
flex-direction: column;
padding: 10px;
background-color: #d2d2d2;
overflow-x:auto;
max-width: 450px;
}
.item {
background-color: #a29f9b;
margin: 5px;
padding: 0 5px;
cursor:pointer;
position: relative;
}
.item2{
min-width:500px
}
.item3{
min-width:700px
}
.modal{
display:none;
position: absolute;
background: #4977d0;
z-index: 100;
}
.modal.show{
display:block;
}
<div class="horizontal-scrollable">
<div class="item item1">
<h1>Item 1</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item2">
<h1>Item 2</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item3">
<h1>Item 3</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item4">
<h1>Item 4</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
</div>
Second option
The second option uses basic CSS to align the modals on the left side - it is much easier to implement and you just have to remove thee left/right/top/bottom property from the modal class and add left:0:
let modal = document.querySelector('.modal');
let items = document.querySelectorAll('.item');
items.forEach(fe);
var mousePos = {};
function fe(item, index){
item.addEventListener("click", function(e){
item.querySelector('.modal').classList.toggle('show');
});
}
.horizontal-scrollable{
display: flex;
flex-direction: column;
padding: 10px;
background-color: #d2d2d2;
overflow-x:auto;
max-width: 450px;
}
.item {
background-color: #a29f9b;
margin: 5px;
padding: 0 5px;
cursor:pointer;
position: relative;
}
.item2{
min-width:500px
}
.item3{
min-width:700px
}
.modal{
display:none;
position: absolute;
background: #4977d0;
left: 0;
z-index: 100;
}
.modal.show{
display:block;
}
<div class="horizontal-scrollable">
<div class="item item1">
<h1>Item 1</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item2">
<h1>Item 2</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item3">
<h1>Item 3</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item4">
<h1>Item 4</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
</div>
Hope I could help :D
You can change the style dynamically and get the position X of your controller, then add the style using JS code.
Also, remove the right 0 from your modal class
let modal = document.querySelector('.modal');
let items = document.querySelectorAll('.item');
items.forEach(fe);
function fe(item, index){
item.addEventListener("click", function(e){
item.querySelector('.modal').style.left = e.clientX + "px";
item.querySelector('.modal').classList.toggle('show');
});
}
.horizontal-scrollable{
display: flex;
flex-direction: column;
padding: 10px;
background-color: #d2d2d2;
overflow-x:auto;
max-width: 450px;
}
.item {
background-color: #a29f9b;
margin: 5px;
padding: 0 5px;
cursor:pointer;
position:relative;
}
.item2{
min-width:500px
}
.item3{
min-width:700px
}
.modal{
display:none;
position: absolute;
top: 100%;
background: #4977d0;
z-index: 100;
}
.modal.show{
display:block;
}
<div class="horizontal-scrollable">
<div class="item item1">
<h1>Item 1</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item2">
<h1>Item 2</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item3">
<h1>Item 3</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
<div class="item item4">
<h1>Item 4</h1>
<div class="modal">
<p>I am modal.</p>
</div>
</div>
</div>
Related
Current Behavior
I have the following basic structure:
<section id="containers">
<div class="box" id="box1">
<div class="collapsible"><h2>Box 1</h2></div>
<div class="content">Content</div>
</div>
<div class="box" id="box2">
<div class="collapsible"><h2>Box 2</h2></div>
<div class="content">Content</div>
</div>
<!-- ... dozens of .boxes ... -->
</section>
#containers is .display: flex; flex-wrap: wrap, so the number of boxes on any one row is dynamic. This is an important feature that must be maintained.
Here's a minimal working example:
$(document).ready(function() {
$(".collapsible").click(function() {
$( this ).next().slideToggle();
});
});
#containers {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
.box {
min-width: 15em;
background: #888;
border: #555 1px solid;
overflow: hidden;
border-radius: 0.5em;
}
.collapsible {
background: #ccc;
cursor: pointer;
}
.collapsible h2 {
margin: 0;
margin-left: 16px;
font-size: 2rem;
}
.collapsible:hover {
background: #aaf;
}
.content {
margin: 0.5em;
margin-left: 16px;
display: none; /* Initially collapsed */
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<p id="status"></p>
<section id="containers">
<div class="box" id="box1">
<div class="collapsible"><h2>Box 1</h2></div>
<div class="content">Content</div>
</div>
<div class="box" id="box2">
<div class="collapsible"><h2>Box 2</h2></div>
<div class="content">Content</div>
</div>
<div class="box" id="box3">
<div class="collapsible"><h2>Box 3</h2></div>
<div class="content">Content</div>
</div>
<div class="box" id="box4">
<div class="collapsible"><h2>Box 4</h2></div>
<div class="content">Content</div>
</div>
<div class="box" id="box5">
<div class="collapsible"><h2>Box 5</h2></div>
<div class="content">Content</div>
</div>
</section>
</body>
I can easily use .slideToggle() to toggle visibility of a sibling (.content) underneath one of the clickable .collapsible divs:
$(".collapsible").click(function() {
$( this ).next().slideToggle();
});
Desired Behavior and Remarks
What I'd like is, on click of any .collapsible div in a row, the entire row will be toggled. That is, every .content div on the same horizontal row as displayed in the current viewport.
This must handle rows with dynamic number of columns, including viewport resizing. I'm flexible on the precise behavior, though.
Is this possible? And how much will it hurt?🙂 Changes to the document structure (such as adding some sort of row container) are OK, and I don't mind using some JS/jQuery code of course. The main thing I can't do is hard code the number of columns, as I need my site to remain responsive on vertical phones and fullscreen desktop browsers.
Maybe the jQuery slideToggle() function is not the best method.
Since a row will be the same height , you may look at a method to set size from 0 to another value. anybox resized will stretch other boxes on the same row.
here an example of the idea, setting a max-height from 0 to 200px and a transition.
it toggles a class.
$(document).ready(function() {
$(".collapsible").click(function() {
this.classList.toggle('slide');// plain javascript to toggle a class
});
});
*{box-sizing:border-box}
#containers {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
.box {
min-width: 15em;
background: #888;
border: #555 1px solid;
overflow: hidden;
border-radius: 0.5em;
}
.collapsible {
background: #ccc;
cursor: pointer;
}
.collapsible h2 {
margin: 0;
margin-left: 16px;
font-size: 2rem;
}
p{margin-top:0;}
.collapsible:hover {
background: #aaf;
}
.content {
margin:0 0.5em;
margin-left: 16px;
max-height:0; /* Initially collapsed */
transition:0.5s
}
.slide + .content{max-height:400px;/* which one got the class*/ color:darkred}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<p id="status"></p>
<section id="containers">
<div class="box" id="box1">
<div class="collapsible"><h2>Box 1</h2></div>
<div class="content"><p>Content</p></div>
</div>
<div class="box" id="box2">
<div class="collapsible"><h2>Box 2</h2></div>
<div class="content"><p>Content</p><p>Content</p></div>
</div>
<div class="box" id="box3">
<div class="collapsible"><h2>Box 3</h2></div>
<div class="content"><p>Content</p></div>
</div>
<div class="box" id="box4">
<div class="collapsible"><h2>Box 4</h2></div>
<div class="content"><p>Content</p><p>Content</p><p>Content</p></div>
</div>
<div class="box" id="box5">
<div class="collapsible"><h2>Box 5</h2></div>
<div class="content"><p>Content</p></div>
</div>
</section>
</body>
What you are missing here , is to set the height of the row to the height of the taller box, unless they will all be the same height.
For this, you can look for every box at the same top offset that the one clicked, and look for the tallest innercontent of the .contents and use this height .
Here comes the idea looking where each are standing and resets a max-height rule, you can inspire from too:
// defaut : supposed to be with no class 'slide' set on html elements
$(document).ready(function () {
let boxes = document.querySelectorAll(".collapsible");
let contents = document.querySelectorAll(".content");
$(".collapsible").click(function (event) {
let arrayContent = [];//reset
let hide=false;
for (i = 0; i < contents.length; i++) {
contents[i].style.maxHeight = "min-content";
let index = i;
let heightC = contents[i].offsetTop;
let boxOffset = contents[i].parentNode.offsetTop + 1;
// a few infos .add/remove what is needed
arrayContent.push({
index,
heightC,
boxOffset
});
contents[i].setAttribute("style", "");// resets inline style
}
let rowOffset = this.offsetTop;
if(this.classList.contains('slide')) {
hide=true;
}
let classState = this.classList;
arrayContent.forEach(function (obj) {
if (obj.boxOffset == rowOffset) {
if(hide == true) boxes[obj.index].classList.add('slide');/* reset needed if window resized => rows reorganized ? */
boxes[obj.index].classList.toggle("slide");
} else {
boxes[obj.index].classList.remove("slide");
}
});
});
});
* {
box-sizing: border-box
}
#containers {
display: flex;
flex-wrap: wrap;
gap: 1em;
}
.box {
min-width: 15em;
background: #888;
border: #555 1px solid;
overflow: hidden;
border-radius: 0.5em;
}
.collapsible {
background: #ccc;
cursor: pointer;
}
.collapsible h2 {
margin: 0;
margin-left: 16px;
font-size: 2rem;
}
p {
margin-top: 0;
}
.collapsible:hover {
background: #aaf;
}
.content {
margin: 0 0.5em;
margin-left: 16px;
max-height: 0;
/* Initially collapsed */
transition: max-height 0.5s!important
}
.slide~.content {
max-height: 400px;
/* which one got the class*/
color: darkred;
}
.collapsible:before {
content: attr(class)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<p id="status"></p>
<section id="containers">
<div class="box" id="box1">
<div class="collapsible">
<h2>Box 1</h2>
</div>
<div class="content">
<p>Content</p>
</div>
</div>
<div class="box" id="box2">
<div class="collapsible">
<h2>Box 2</h2>
</div>
<div class="content">
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="box" id="box3">
<div class="collapsible">
<h2>Box 3</h2>
</div>
<div class="content">
<p>Content</p>
</div>
</div>
<div class="box" id="box4">
<div class="collapsible">
<h2>Box 4</h2>
</div>
<div class="content">
<p>Content</p>
<p>Content</p>
<p>Content</p>
</div>
</div>
<div class="box" id="box5">
<div class="collapsible">
<h2>Box 5</h2>
</div>
<div class="content">
<p>Content</p>
</div>
</div>
</section>
</body>
I created 2 buttons that scroll the DIV left and right. However, it scrolls a fixed width. I want it to scroll each column of Bootstrap 5 on clicking Prev/Next.
or in simpler terms, I want it to scroll one column each to the left or right as per the click and not 100px each as it currently does. Please help.
DEMO JSFiddle: https://jsfiddle.net/hsmx2f5z/
HTML
<div class="nav-scroller">
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="row nav" id="boxSlider">
<div class="col-md-3 nav-scroller__eighty">
<div class="card">
<div class="card-body">
<h5>Title 1</h5>
<p>Some information about the slider. Some information about the slider. Some information about the slider. Some information about the slider.</p>
</div>
</div>
</div>
<div class="col-md-3 nav-scroller__eighty">
<div class="card">
<div class="card-body">
<h5>Title 2</h5>
<p>Some information about the slider. Some information about the slider. Some information about the slider. Some information about the slider.</p>
</div>
</div>
</div>
<div class="col-md-3 nav-scroller__eighty">
<div class="card">
<div class="card-body">
<h5>Title 3</h5>
<p>Some information about the slider. Some information about the slider. Some information about the slider. Some information about the slider.</p>
</div>
</div>
</div>
<div class="col-md-3 nav-scroller__eighty">
<div class="card">
<div class="card-body">
<h5>Title 4</h5>
<p>Some information about the slider. Some information about the slider. Some information about the slider. Some information about the slider.</p>
</div>
</div>
</div>
<div class="col-md-3 nav-scroller__eighty">
<div class="card">
<div class="card-body">
<h5>Title 5</h5>
<p>Some information about the slider. Some information about the slider. Some information about the slider. Some information about the slider.</p>
</div>
</div>
</div>
<div class="col-md-3 nav-scroller__eighty">
<div class="card">
<div class="card-body">
<h5>Title 6</h5>
<p>Some information about the slider. Some information about the slider. Some information about the slider. Some information about the slider.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<input id="btnLeft" type="Button" value="Prev"/>
<input id="btnRight" type="Button" value="Next" />
CSS:
.nav-scroller {
position: relative;
z-index: 2;
overflow-y: hidden;
}
.nav-scroller .nav {
display: flex;
flex-wrap: nowrap;
margin-top: -1px;
overflow-x: auto;
color: rgba(255, 255, 255, .75);
text-align: center;
white-space: nowrap;
-webkit-overflow-scrolling: touch;
}
.nav-underline .nav-link {
padding-top: 50px;
padding-bottom: 50px;
font-size: 14px;
color: #6c757d;
min-width: 100px;
}
.nav-underline .nav-link:hover {
color: #007bff;
}
.card-body p {
color: #393939;
white-space: pre-wrap;
}
.nav-underline .active {
font-weight: 500;
color: #343a40;
}
.nav-scroller__eighty {
width: 80%;
max-width: 80%;
}
JS:
const boxSlider = document.getElementById('boxSlider');
document.getElementById("btnLeft").onclick = () => {
boxSlider.scroll({
left: boxSlider.scrollLeft + 200,
behavior: 'smooth'
});
}
document.getElementById("btnRight").onclick = () => {
boxSlider.scroll({
left: boxSlider.scrollLeft - 200,
behavior: 'smooth'
});
}
Your best bet is probably to scroll based on the width of the column elements, like this:
boxSlider.scroll({
left: boxSlider.scrollLeft + widthOfColumn,
behavior: 'smooth'
});
You can get the width of a column like this:
// Assuming all columns are the same width, get the width of the first column
boxSlider.querySelector(".nav-scroller__eighty").offsetWidth
Your code should look something like this
const boxSlider = document.getElementById('boxSlider');
document.getElementById("btnLeft").onclick = () => {
boxSlider.scroll({
left: boxSlider.scrollLeft + boxSlider.querySelector(".nav-scroller__eighty").offsetWidth,
behavior: 'smooth'
});
}
document.getElementById("btnRight").onclick = () => {
boxSlider.scroll({
left: boxSlider.scrollLeft - boxSlider.querySelector(".nav-scroller__eighty").offsetWidth,
behavior: 'smooth'
});
}
I'm trying to build a long scrollable list of grouped items. The group titles should always be visible (stacked).
If you click the groupheader you should scroll to the responding items.
Using position sticky i managed to make the groupheaders stay in view. (Using sticky may have some compatibility issues with IE).
I then set click event to scroll to the sticky header but that didnt do the trick as it doesn't really position it nicely. I've set it to the groupitems but they get behind the sticky headers.
To clearify my question i've made a visual example:
i've created a jsfiddle with what i got so far: https://jsfiddle.net/n6urjabk/1/
<style type="text/css">
body,
html {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
body {
background: #20262E;
padding: 20px;
box-sizing: border-box;
font-family: Helvetica;
}
#container {
/*display:flex;*/
max-height: 100%;
height: 400px;
}
.column {
background: #eee;
box-sizing: border-box;
overflow: auto;
position: relative;
max-height: 400px;
}
.row {
background: #eee;
border-radius: 0px;
margin: 0;
padding: 10px;
}
.row:nth-child(odd) {
background: #fff;
}
.column h4 {
background: lightblue;
padding: 10px;
margin: 0;
position: sticky;
height: 40px;
box-sizing: border-box;
text-align: center;
}
.column h4:hover {
opacity: 0.8;
cursor: pointer;
}
.column h4:nth-of-type(odd) {
background: lightgreen;
}
</style>
<div id="container">
<div class="column">
<h4 class="header1" id="test1">
Head 1
</h4>
<div class="content">
<div class="row">row 1.1</div>
<div class="row">row 1.2</div>
<div class="row">row 1.3</div>
<div class="row">row 1.4</div>
<div class="row">row 1.5</div>
<div class="row">row 1.6</div>
<div class="row">row 1.7</div>
<div class="row">row 1.8</div>
</div>
<h4 class="header2" id="test2">
Head 2
</h4>
<div class="content">
<div class="row">row 2.1</div>
<div class="row">row 2.2</div>
<div class="row">row 2.3</div>
<div class="row">row 2.4</div>
<div class="row">row 2.5</div>
<div class="row">row 2.6</div>
<div class="row">row 2.7</div>
<div class="row">row 2.8</div>
</div>
<h4 class="header3" id="test3">
Head 3
</h4>
<div class="content">
<div class="row">row 3.1</div>
<div class="row">row 3.2</div>
<div class="row">row 3.3</div>
<div class="row">row 3.4</div>
<div class="row">row 3.5</div>
<div class="row">row 3.6</div>
<div class="row">row 3.7</div>
<div class="row">row 3.8</div>
</div>
<h4 class="header4" id="test4">
Head 4
</h4>
<div class="content">
<div class="row">row 4.1</div>
<div class="row">row 4.2</div>
<div class="row">row 4.3</div>
<div class="row">row 4.4</div>
<div class="row">row 4.5</div>
<div class="row">row 4.6</div>
<div class="row">row 4.7</div>
<div class="row">row 4.8</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
var headers = $('h4').length;
var headerHeight = 40;
var maxOffset = (headers * headerHeight) - headerHeight;
$('h4').each(function() {
var index = $(this).index('h4');
var top = index * headerHeight;
var bottom = maxOffset - top;
$(this).css('top', top).css('bottom', bottom);
});
$('h4').on('click', function() {
$(this).next()[0].scrollIntoView({
block: 'start',
behavior: 'smooth'
});
});
</script>
you need to offset the scroll parameter as you did for the top. I'm not so good in jQuery so I have written a function in JS that works. but you can understand to gist of it and write one yourself.
click event function:
document.addEventListener("click", (e) => {
if (e.target.nodeName == "H4") {
const index = parseInt(e.target.id.split("").pop());
const scrollNum = e.target.nextElementSibling.offsetTop - (index * 40);
document.querySelector(".column").scrollTo({
top: scrollNum,
behavior: 'smooth'
});
}
});
I have these progress bars which are suppose to work as ratings and they look good:
I have applied some CSS and I change their width with JavaScript by reading values from text files.
But are not responsive at all and whenever the window is resized:
HTML:
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<div class="second-part">
<div class="row">
<div class="side">
<div>5 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar11" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p11">150</div>
</div>
<div class="side">
<div>4 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar12" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p12">63</div>
</div>
<div class="side">
<div>3 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar13" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p13">15</div>
</div>
<div class="side">
<div>2 stars</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar14" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p14">6</div>
</div>
<div class="side">
<div>1 star</div>
</div>
<div class="middle">
<div class="bar-container">
<div class="bar15" style="width: 10% ; height: 18px; background-color: gold;"></div>
</div>
</div>
<div class="side right">
<div class="p15">20</div>
</div>
</div>
</div>
CSS:
* {
box-sizing: border-box;
}
/* Three column layout */
.side {
float: left;
width: 15%;
margin-top:10px;
}
.middle {
margin-top:10px;
float: left;
width: 70%;
}
/* Place text to the right */
.right {
text-align: left;
}
/* Clear floats after the columns */
.row:after {
content: "";
display: table;
clear: both;
}
/* The bar container */
.bar-container {
width: 90%;
background-color: #f1f1f1;
text-align: center;
color: white;
}
/* Responsive layout - make the columns stack on top of each other instead of next to each other */
#media (max-width: 400px) {
.side, .middle {
width: 100%;
}
.right {
display: none;
}
}
JavaScript to change progress bar width:
var par1 = 4;
for(var i = 10; i < 16; i++) {
$('.p' + (i+1)).text(table[0][par1]);
$('.bar' + (i+1)).css("width", table[0][par1]);
par1++;
}
How could I make it more responsive? Thank you in advance!
I recommend using css flexbox, so the items wrap instead of overlap when the page is resized. You could use media queries with this to adjust the size of the items and container so they don't overlap/wrap. This site has a good explanation of flexbox: A Complete Guide to Flexbox.
basically I have a function that resizes elements accordingly with jquery triggering the function on end of the resizing of the window.
it works perfectly apart from when I resize the window back to original size, I do not see the same thing as if I refresh the page. Which is weird considering the exact same function is being called.
The problem can be seen live here
The Js:
var waitForFinalEvent = (function () {
var timers = {};
return function (callback, ms, uniqueId) {
if (!uniqueId) {
uniqueId = "Don't call this twice without a uniqueId";
}
if (timers[uniqueId]) {
clearTimeout (timers[uniqueId]);
}
timers[uniqueId] = setTimeout(callback, ms);
};
})();
$(window).resize(function () {
waitForFinalEvent(function(){
loadcontext();
//...
}, 10, "some unique string");
});
function loadcontext() {
var winwidth = window.innerWidth;
var winheight = window.innerHeight;
<!-- Fixes layout on screens -->
if (winwidth < 1200)
{
$('#blockscontainer').css("left", (winwidth / 2)*-1 );
$('.block').css("width", (winwidth - 30)/ 5 );
$('.block').css("height", (winwidth - 30)/ 7.5 );
$('#blockscontainer').css("width", winwidth -20);
}
else
{
$('#blockscontainer').css("left", (1200 / 2)*-1 );
$('.block').css("width", 1173 / 5 );
}
};
The CSS:
body { margin: 0px; padding: 0px; }
#contentcontain {clear: both; left: 50%; }
#blockscontainer {clear: both; height: 100%; max-width: 1180px; width: 100%; background- color: #EEE; padding: 10px; border-radius: 15px;}
#blockcontext {overflow: auto;width: 100% clear: both; position: relative; height: 100%; background-color: #DDD;border-radius: 7px; padding-bottom: 20px;}
#footer { width: 100%; margin-top: 30px; text-align: center; background-color: #666; }
#content { background-color: #333; padding-top: 50px;}
.block {display: inline-block; height: 150px; width: 200px; background-color: #FFF; float: left; margin-top: 20px; border: 1px solid #CCC;}
The HTML:
<body onload="loadcontext()">
<div id="content">
<div id="contentcontain" align="center">
<div id="blockscontainer">
<div id="blockcontext">
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
<div class="block">
test content
</div>
</div>
</div>
</div>
<center>
<div id="footer">
content
</div>
</center>
</div>
</body>
</html>
When you resize the window below a width of 1200 px, you call these lines:
$('.block').css("height", (winwidth - 30)/ 7.5 );
$('#blockscontainer').css("width", winwidth -20);
These are causing the issue you see, as they aren't reset to any kind of default when you increase the window size back about 1200px wide. This causes the page to look different because the width of #blockscontainer and the height of every .block element has changed.