I'm trying to make a smooth, infinite, automatic carousel for my images but I'm stuck. I believe I have the carousel moving (thinking I may be moving the wrong div). The part I'm struggling with is to get the images t0o loop back around when they leave the page, making it infinite. I would love some help.
Thanks
LM
const carousel = document.querySelector(".carousel1");
const imageSection = document.querySelector(".imagesection");
let sliders = document.querySelectorAll('.sliders');
let increment= 0;
let index = 1;
const interval = 100;
const firstClone = sliders[0].cloneNode(true);
const lastClone = sliders[sliders.length -1].cloneNode(true);
let check = sliders.offsetHeight
console.log(check)
// Append the firstclone to the back of the carousel
carousel.appendChild(firstClone);
let timer = setInterval(() => {
increment++
carousel.style.transform = `translateY(-${increment}px)`
console.log('hey')
}, interval);
.imagesection{
width: 50%;
border: 1px solid blue;
display: flex;
flex-direction: row;
overflow: hidden;
}
.carousel1{
border: 1px solid pink;
width: 35%;
margin:0 2.5px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.sliders{
border-radius: 5px;
width: 100%;
height: 300px;
margin: 5px 0;
object-fit: cover;
}
.images{
border-radius: 5px;
width: 100%;
height: 100%;
<div class="container">
<div class="heading">
<h1>Hey Luke</h1>
</div>
<div class="imagesection">
<!-- IMAGE SECTION 1 -->
<div class="carousel1">
<div class="sliders">
<img class="images" src="./images/bekir-donmez-eofm5R5f9Kw-unsplash.jpg" alt="clone">
</div>
<div class="sliders">
<img class="images" src="./images/conscious-design-eZIE5ZFR7Cs-unsplash.jpg" alt="second clone">
</div>
<div class="sliders">
<img class="images" src="./images/dane-wetton-t1NEMSm1rgI-unsplash.jpg" alt="third clone">
</div>
<div class="sliders">
<img class="images" src="./images/ginny-rose-stewart-UxkcSzRWM2s-unsplash (1).jpg" alt="">
</div>
</div>
Related
I have a UI that involves (on wider devices) a 2 column layout that scroll in opposite directions in an infinite loop. On page load the UI seems to work pretty well but I really need some help improving some aspects of it.
The key things I want to work on are:
Order of items (projects) matches HTML structure. Currently they're reversed
Improve how the UI reacts and displays on browser resize
Fix ESLint undefined errors for "Map" and Weakmap"
1. Order of Items (projects)
You can see I've number each .project and on load the one that appears last in the HTML is first when viewing the webpage. It would make more sense the 'top' item is visible in the viewport before revealing the others in cascading order on scroll.
2. UI on Browser Resize
Though the UI seems to work well on page load, I think due to the positional values set on each .project this seems to lead to content overlapping or getting cropped on resize. I've tried matchMedia to see if I can run/recalculate once the viewport has 'stopped' resizing but doesn't seem to work.
It doesn't seem as bad going from desktop to mobile size screens. But vice versa, if you open on a narrow viewport and enlarge no content is visible and the UI appears empty until you scroll ...and then the left column doesn't loop (it stops) until you refresh the page.
On the mid-point #media when each .project has 50vh and not 100vh on scroll the items appear to flicker. Again, until you refresh.
It seems like maybe I need to run the script again after each resize? This is for a 'fun' portfolio style project so I appreciate that's a bit heavy on the resource but maybe acceptable in this instance, as it's not a commercial or D2C site?
3. ESLint Errors
Lastly, I get 2 errors saying Map and Weakmap are undefined when I compile using CodeKit and ESLint. That is in relation to these 2 lines...
const lastScrollPos = new WeakMap();
const linkedLoops = new Map([
I know there's a couple of issues but I wanted to break them down to try and be as clear as possible.
const leftLoop = document.querySelector(".split-loop__left");
const rightLoop = document.querySelector(".split-loop__right");
const scrollHeight = leftLoop.scrollHeight;
const offsetBoundary = 200; //the offset from the borders at which the element reordering event is triggered
const lastScrollPos = new WeakMap();
const linkedLoops = new Map([
[leftLoop, rightLoop],
[rightLoop, leftLoop]
]);
let scrollLockElement = null;
let scrollLockTimeout = null;
// the function sets handlers to scrolling for infinite scrolling
function infiniteScrollHandler(loop) {
const virtualLoop = Array.from(loop.children);
virtualLoop.forEach(
(el) => (el.style.top = scrollHeight / 2 + el.offsetHeight + "px")
);
loop.addEventListener("scroll", () => {
if (virtualLoop.length < 2) return; // not enough items to scroll
const topBound = loop.scrollTop;
const bottomBound = loop.scrollTop + loop.offsetHeight;
const firstEl = virtualLoop[0];
const lastEl = virtualLoop[virtualLoop.length - 1];
if (firstEl.offsetTop >= topBound - offsetBoundary) {
lastEl.style.top = firstEl.offsetTop - lastEl.offsetHeight + "px";
virtualLoop.unshift(lastEl);
virtualLoop.pop();
} else if (
lastEl.offsetTop + lastEl.offsetHeight <
bottomBound + offsetBoundary
) {
firstEl.style.top = lastEl.offsetTop + lastEl.offsetHeight + "px";
virtualLoop.push(firstEl);
virtualLoop.shift();
}
});
}
// the function sets handlers to scrolling for reverse interaction with the linked loop
function reverseLinkLoopHandler(loop) {
loop.addEventListener("scroll", () => {
const delta = lastScrollPos.get(loop) - loop.scrollTop;
lastScrollPos.set(loop, loop.scrollTop);
// this is blocked to prevent deadlock when events of two blocks are called each other.
{
if (scrollLockElement !== null && scrollLockElement !== loop)
return;
scrollLockElement = loop;
clearTimeout(scrollLockTimeout);
scrollLockTimeout = setTimeout(
() => (scrollLockElement = null),
300
);
}
linkedLoops
.get(loop)
.scrollTo(0, linkedLoops.get(loop).scrollTop + delta);
});
}
// set scroll handlers on all loops
linkedLoops.forEach((loop) => {
infiniteScrollHandler(loop);
loop.scrollTo(0, scrollHeight / 2);
lastScrollPos.set(loop, scrollHeight / 2);
reverseLinkLoopHandler(loop);
});
/* Hide Scroll Bars */
::-webkit-scrollbar {
display: none;
}
html,
body {
margin: 0;
padding: 0;
-ms-overflow-style: none;
scrollbar-width: none;
}
/* Content will be in these eventually */
.bar-left,
.bar-right {
border-right: 2px solid black;
box-sizing: border-box;
height: 100vh;
position: fixed;
top: 0;
left: 0;
width: 48px;
z-index: 10000;
}
.bar-right {
border: none;
border-left: 2px solid black;
left: auto;
right: 0;
}
/* Split Loop */
.split-loop {
margin-left: 24px;
}
.split-loop__item {
background: white;
overflow: hidden;
}
.project {
box-sizing: border-box;
border-bottom: 2px solid black;
padding: 24px 24px 0;
width: 100%;
}
.project__media {
margin-bottom: 24px;
}
.project__img {
border: 2px solid black;
width: 100%;
max-width: 100%;
}
.project__title {
font-family: Arial;
font-size: 12px;
margin-bottom: 24px;
}
/* Tablet View */
#media screen and (min-width: 400px) {
.split-loop {
height: 100vh;
position: relative;
margin: 0 48px;
}
.split-loop__left {
border-right: 2px solid black;
box-sizing: border-box;
width: 50%;
}
.split-loop__right {
position: fixed;
right: 24px;
bottom: 0;
width: calc(50% - 48px);
}
.split-loop__item {
display: flex;
flex-flow: column;
height: 50vh;
}
.project__media {
display: flex;
flex-grow: 1;
align-items: center;
justify-content: center;
overflow: hidden;
margin-bottom: 24px;
}
.project__img {
box-sizing: border-box;
display: block;
margin-bottom: 0;
width: auto;
max-width: 100%;
height: 100%;
max-height: 100%;
object-fit: contain;
overflow: hidden;
}
/* Split Loop */
.split-loop {
position: relative;
margin: 0 48px;
}
.split-loop__left {
width: 50%;
overflow: auto;
position: relative;
max-height: 100vh;
}
.split-loop__right:before,
.split-loop__left:before {
display: block;
content: "";
z-index: -1;
height: 9999999px;
}
.split-loop__right {
box-sizing: border-box;
position: fixed;
right: 48px;
bottom: 0;
z-index: 5;
width: calc(50% - 48px);
overflow: auto;
max-height: 100vh;
}
.project {
box-sizing: border-box;
border-bottom: 2px solid black;
padding: 24px 24px 0;
position: absolute;
}
}
#media screen and (min-width: 600px) {
.split-loop__item {
height: 100vh;
}
}
<header class="bar-left"></header>
<div class="bar-right"></div>
<div class="split-loop" role="main">
<div class="split-loop__left">
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #1</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #2</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #3</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Left #4</h2>
</div>
</div>
</div>
<div class="split-loop__right">
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #1</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #2</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #3</h2>
</div>
</div>
<div class="split-loop__item project">
<div class="project__media">
<img src="https://www.fillmurray.com/g/600/800" alt="" class="project__img" />
</div>
<div class="project__copy">
<h2 class="project__title">Project Right #4</h2>
</div>
</div>
</div>
</div>
I am trying to move images inside of a container using Javascript. Ultimately, I want to move it using setTimeout, but for now trying to do it using an event listener on a button click. It seems to work, but only once. I want to keep moving the images when the button is clicked. Any help is helpful and appreciated.
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"/>
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"/>
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"/>
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80"/>
</div>
</div>
<button id="moveIt">MOVE</button>
<style>
.container {
display: flex;
justify-content: space-around;
overflow: hidden;
max-width: 100%;
z-index: 222;
}
.images {
width: 300px !important;
display: block;
text-align: center;
margin-right: 10px;
height: 400px !important;
}
</style>
<script>
let images = document.querySelectorAll('.images');
const moveBtn = document.getElementById('moveIt');
let pleaseWork = () => {
for(i=0; i < images.length; i++) {
images[i].style.marginLeft = "-300px";
}
}
moveBtn.addEventListener('click', pleaseWork);
</script>
You are setting margin-left to a static number rather than incrementing it. Here's an example that accesses the current margin-left, strips it of the 'px', converts that to a number, then increments it and applies it back to the element.
let images = document.querySelectorAll('.images');
const moveBtn = document.getElementById('moveIt');
let increment = -10
let pleaseWork = () => {
for (i = 0; i < images.length; i++) {
let ml = Number(images[i].style.marginLeft.replaceAll('px', ''))
ml += increment
images[i].style.marginLeft = `${ml}px`;
}
}
moveBtn.addEventListener('click', pleaseWork);
.container {
display: flex;
justify-content: space-around;
overflow: hidden;
max-width: 100%;
z-index: 222;
}
.images {
width: 300px !important;
display: block;
text-align: center;
margin-right: 10px;
height: 400px !important;
}
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" />
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" />
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" />
</div>
<div class="images">
<img src="https://images.unsplash.com/photo-1596536220655-21429cf12ae0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80" />
</div>
</div>
<button id="moveIt">MOVE</button>
So I have been learning animations with JS,CSS,HTML and I was trying to learn how to animate a scroll similar to a this
I have tried to use jQuery-SlotMachine though I am very lost on how the action is executed even with the JS code next to it. Could someone explain me how I can code this with the same API or another or Code it in vanilla JS.
You can try CSS animations with a little javascript code to control your custom animation state.
I think my sample could help you.
CodePen
$(document).ready(function() {
let $elements = $(".element");
let $transitionList = $(".transition-list");
let currentIndex = 0;
setInterval(function() {
$transitionList.css(
"transform",
"translateY(" + currentIndex * -250 + "px)"
);
currentIndex++;
if ($elements.length - 1 < currentIndex) {
currentIndex = 0;
}
}, 750);
});
body {
display: flex;
align-items: center;
justify-content: center;
}
.container {
display: flex;
width: 50%;
}
.center {
align-items: center;
justify-content: center;
}
.border-container {
border: 25px solid #dfe0a0ed;
border-radius: 30%;
overflow: hidden;
}
.transition-list {
width: 250px;
height: 250px;
background-color: #fefefe;
transition-property: all;
transition-duration: 0.5s;
transition-timing-function: cubic-bezier(0, 1, 0.1, 0.2, 0.7, 1);
}
.element {
background-color: #6f6f6f;
width: 250px;
height: 250px;
font-size: 188px;
display: flex;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css">
<div class="conainer center">
<div class="border-container">
<div class="transition-list">
<div class="element center"><i class="fas fa-clock"></i></div>
<div class="element center"><i class="fas fa-unlock"></i></div>
<div class="element center"><i class="fas fa-th"></i></div>
<div class="element center"><i class="fas fa-american-sign-language-interpreting"></i></div>
</div>
</div>
</div>
1. To begin, you must have a container:
<div id="theContainer" class="container">
</div>
2. Great, now let's put some images in it.
<div id="theContainer" class="container">
<img src="https://picsum.photos/100/?random">
<img src="https://picsum.photos/100/?random">
<img src="https://picsum.photos/100/?random">
</div>
3. Now, let's add two buttons to move it:
<div id="theContainer" class="container">
<img src="https://picsum.photos/100/?image=0">
<img src="https://picsum.photos/100/?image=1">
<img src="https://picsum.photos/100/?image=2">
</div>
<button id="prev" value="Previous">
<button id="next" value="Next">
4. Sweet! We got our HTML, now we just got to add our Javascript:
// Set up previous button
const btnPrev = document.querySelector('#prev');
// Set up Next Button
const btnNext = document.querySelector('#next');
// Set up our container
const el = document.querySelector('#theContainer');
// Create new SlotMachine
const slot = new SlotMachine(el, {});
// Add Event Listeners or do things when we click it
btnPrev.addEventListener('click', () => slot.prev());
btnNext.addEventListener('click', () => slot.next());
<link href="https://cdn.jsdelivr.net/npm/jquery-slotmachine#4.0.0/dist/jquery.slotmachine.min.css"></style>
<div id="theContainer" class="container" style="width: 100px; height: 100px">
<div><img src="https://picsum.photos/100/?image=0"></div>
<div><img src="https://picsum.photos/100/?image=1"></div>
<div><img src="https://picsum.photos/100/?image=2"></div>
</div>
<button id="prev">Previous</button>
<button id="next">Next</button>
<!-- Add script files -->
<script src="https://cdn.jsdelivr.net/npm/jquery-slotmachine#4.0.0/dist/slotmachine.min.js"></script>
5. Notes:
you must add a width & height to #theContainer. (style="width: 100px; height: 100px")
the images must be surrounded by a block element. (<div><img /></div>)
I'm trying to make it so that the pink '#images-wrap' has the same height as the main image. Whenever there are too many small rollover images on the right, it pushes the height of the pink div to exceed the main image. If I could get it to match it's height instead, then I could use overflow hidden to not display the excess rollover images underneath and use overflow as scroll-y so the can scroll down to see the excess small images.
Displaying as a table doesn't work - you'd think a simple child div and hidden overflows would do the trick, but you can't as you can't set the height, otherwise the image aspect ratios wouldn't resize. The images must keep their 3:2 aspect ratios.
The javascript in this solution doesn't work as presumably it cannot fetch the image's height. I've also tried to fetch the height of the child image and this also failed.
Does anyone know of a magic trick that can achieve this?
Really appreciate any help here, thanks!
#images-wrap {
width: 50%;
height: auto;
margin-top: 25px;
float: left;
display: flex;
background: red;
max-height: 150px;
}
#details-wrap {
width: 100%;
height: 325px;
float: left;
text-align: right;
position: relative;
}
#main-image {
width: 80.5%;
float: left;
background-size: cover !important;
background-position: center center !important;
height: auto;
}
#main-image>img {
display: block;
width: 100%;
height: auto;
margin: 0;
}
#image-thumbs {
width: 17.5%;
height: auto;
float: left;
margin-left: 2%;
overflow-y: scroll !important;
/* make it only scroll when exceeds height of main image */
/* max-height: 400px; make this the height of #main-image */
}
.image-thumb {
margin-bottom: 6px;
background-position: center;
background-size: cover;
height: auto;
}
.image-thumb:last-of-type {
margin-bottom: 0;
}
.image-thumb>img {
height: auto;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="images-wrap">
<div id="main-image" style="background-image: url('http://elephant-family.org/wp-content/uploads/2015/06/shutterstock_77217466.jpg')">
<img src="https://cml.sad.ukrd.com/tp/3x2/" id="main-image-sizer">
</div>
<div id="image-thumbs">
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Ffortunedotcom.files.wordpress.com%2F2014%2F09%2F174187214.jpg&w=800&q=85')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Ffortunedotcom.files.wordpress.com%2F2014%2F09%2F174187214.jpg&w=800&q=85')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('http://streamafrica.com/wp-content/uploads/2014/01/african-lion-wallpapers-hd-648x372.jpg')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Ffortunedotcom.files.wordpress.com%2F2014%2F09%2F174187214.jpg&w=800&q=85')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('http://streamafrica.com/wp-content/uploads/2014/01/african-lion-wallpapers-hd-648x372.jpg')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<script>
// hides overflow scroll if less than 5 thumbs
var thumbs = document.getElementsByClassName('image-thumb');
var thumbsWrap = document.getElementById('image-thumbs');
if (thumbs.length < 5) {
thumbsWrap.style.overflow = 'hidden';
}
</script>
<script>
// makes '#image-thumbs' not exceed the height of '#main-image'
var mainImgHeight = document.getElementById('main-image-sizer').style.height;
var imageThumbsInitialHeight = document.getElementById('image-thumbs').style.height;
if (imageThumbsInitialHeight > mainImgHeight) {
document.getElementById('image-thumbs').style.height = mainImgHeight;
}
</script>
</div>
</div>
You can use display: flex on the main container:
#images-wrap {
width: 100%;
height: auto;
margin-top: 25px;
float: left;
display: flex;
}
#details-wrap {
width: 100%;
height: 325px;
float: left;
text-align: right;
position: relative;
}
#main-image {
width: 80.5%;
float: left;
background-size: cover !important;
background-position: center center !important;
height: auto;
}
#main-image>img {
display: block;
width: 100%;
height: auto;
margin: 0;
}
#image-thumbs {
width: 17.5%;
height: auto;
float: left;
margin-left: 2%;
overflow-y: scroll !important;
/* make it only scroll when exceeds height of main image */
/* max-height: 400px; make this the height of #main-image */
}
.image-thumb {
margin-bottom: 6px;
background-position: center;
background-size: cover;
height: auto;
}
.image-thumb:last-of-type {
margin-bottom: 0;
}
.image-thumb>img {
height: auto;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="images-wrap">
<div id="main-image" style="background-image: url('http://elephant-family.org/wp-content/uploads/2015/06/shutterstock_77217466.jpg')">
<img src="https://cml.sad.ukrd.com/tp/3x2/" id="main-image-sizer">
</div>
<div id="image-thumbs">
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Ffortunedotcom.files.wordpress.com%2F2014%2F09%2F174187214.jpg&w=800&q=85')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('http://streamafrica.com/wp-content/uploads/2014/01/african-lion-wallpapers-hd-648x372.jpg')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Ffortunedotcom.files.wordpress.com%2F2014%2F09%2F174187214.jpg&w=800&q=85')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('http://streamafrica.com/wp-content/uploads/2014/01/african-lion-wallpapers-hd-648x372.jpg')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('https://imagesvc.timeincapp.com/v3/mm/image?url=https%3A%2F%2Ffortunedotcom.files.wordpress.com%2F2014%2F09%2F174187214.jpg&w=800&q=85')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<div class="image-thumb" onmouseover="$('#main-image').css('background-image', $(this).css('background-image'));" style="background-image: url('http://streamafrica.com/wp-content/uploads/2014/01/african-lion-wallpapers-hd-648x372.jpg')">
<img src="https://cml.sad.ukrd.com/tp/3x2/">
</div>
<script>
// hides overflow scroll if less than 5 thumbs
var thumbs = document.getElementsByClassName('image-thumb');
var thumbsWrap = document.getElementById('image-thumbs');
if (thumbs.length < 5) {
thumbsWrap.style.overflow = 'hidden';
}
</script>
<script>
// makes '#image-thumbs' not exceed the height of '#main-image'
var mainImgHeight = document.getElementById('main-image-sizer').style.height;
var imageThumbsInitialHeight = document.getElementById('image-thumbs').style.height;
if (imageThumbsInitialHeight > mainImgHeight) {
document.getElementById('image-thumbs').style.height = mainImgHeight;
}
</script>
</div>
</div>
I have a div-container, which has one main image and optional multiple smaller images: http://jsfiddle.net/h5kc8ybm/
The multiple smaller images are generated dynamically, so there can be just 1 or 10 of them. On my JFiddle you can see, that the images are just displayed in one single row.
What I want to achieve is, that there are filled up 'by colomns':
First image on top next to the main image (like shown in this example)
Second image below that (not right of it, like in the example)
Third image right of first image (top)
Fourth image below third image
...and so on.
Is it possible to do that just with CSS?
Update
To avoid misunderstanding: All smaller images should be positioned right of the main image. But these small images should be displayed in two rows, filled up from first row to second row.
The main div-element will never change its height, but only its width.
Example
HTML
<div class="tnwrapper">
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail">
</div>
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail child">
</div>
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail child">
</div>
</div>
LESS
.tnwrapper {
background-color: #f5f5f5;
padding: 5px 5px 5px 9px;
border-radius: 4px;
display: inline-block;
.tn {
display: inline-block;
vertical-align:top;
position: relative;
margin-right: 5px;
.thumbnail {
display: block;
padding: 4px;
margin-bottom: 20px;
line-height: 1.42857143;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 4px;
}
.thumbnail.child {
width: 40px;
}
}
}
I was able to do this with the following steps:
wrap the smaller children in a div and make it position:relative
apply position:absolute on even items and reposition them
float them left
http://jsfiddle.net/0neukb08/
The downside of this approach is that it hardcodes the image's size in the "reposition" step
Additionally, the reason I chose not to use flex-box here was this issue with growing its width (I also didn't like the highest voted answer), but flexbox is a good option if you know the container's width in advance.
You probably can do this by
Rotate the container -90deg and reflect it:
.tnwrapper {
...
transform: rotate(-90deg) scaleX(-1);
}
then apply the reverse transformation for the thumbnails:
.tnwrapper .tn {
...
transform: rotate(90deg) scaleX(-1);
}
JSFiddle: http://jsfiddle.net/h5kc8ybm/1/
Note though that the height limit of the container is now width, not height (because it was rotated -90deg.
CSS flexbox styling should do the trick:
.tnwrapper {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 200px;
}
.tn:first-child {
height: 192px;
width: 192px;
}
<div class="tnwrapper">
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail">
</div>
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail child">
</div>
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail child">
</div>
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail child">
</div>
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail child">
</div>
<div class="tn">
<img src="http://placehold.it/96x96" alt="" class="thumbnail child">
</div>
</div>
EDIT: Sorry, the above snippet doesn't quite answer the question after all. This snippet places each subsequent image in left-to-right then top-to-bottom order, rather than top-to-bottom then left-to-right order as the question asked. I think adding a div around the first image would be the cleanest way to accomplish what you want.
I'm not quite clear on the order of the thumbnails but I think you wanta column format for those.
I that case wrap the main image and the thumbnails in separate divs and then flexbox can do the rest.
.wrap {
display: flex;
margin: 1em auto;
height: 280px;
}
.hero {
padding: 10px;
}
.sidekicks {
flex: 1;
padding: 10px;
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-content: flex-start;
}
.sidekicks .item {
width: 96px;
height: 96px;
margin: 10px;
background: lightblue;
line-height: 96px;
text-align: center;
}
<div class="wrap">
<div class="hero">
<img src="http://lorempixel.com/image_output/city-h-c-240-250-5.jpg" alt="" />
</div>
<div class="sidekicks">
<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>
</div>
Codepen Demo
This is solution with flexbox and since you said that height of main-div wont change this should work http://jsfiddle.net/h5kc8ybm/13/
CSS
.tnwrapper {
background-color: #000;
padding: 5px 5px 5px 9px;
border-radius: 4px;
display: -webkit-flex;
display: flex;
}
.child-images {
display: -webkit-flex;
display: flex;
-webkit-flex-direction: column;
flex-direction: column;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
margin: 0 10px;
height: 170px;
}
.tnwrapper .tn .thumbnail {
padding: 4px;
margin: 10px;
line-height: 1.42857143;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 4px;
}
.child-images .tn img {
width: 40px;
}