My aim is to display a different image or video displayed within a div, which changes when other elements are hovered over.
I think I have this working with just an image by checking what image file is specified in a data-src and loading that into an img tag on the page. However I need to change the markup from img to video when a movie file is specifed - that's what I need help with.
You can see the 'working' image version here (not the 3rd item has a placeholder video in the data-src so won't show):
https://codepen.io/moy/pen/BaNxzdL
So currently on the page I have this empty image tag:
<div class="carousel__bg">
<img src="" />
</div>
Image files are specified on multiple carousel items in a data-src like the example below:
<div class="carousel__item" data-src="img/content/1-wide.jpg">
<div class="carousel__content">
<h4 class="carousel__title">Behind The Scenes</h4>
<span class="carousel__flag">// Featured</span>
<h2 class="carousel__subtitle">Denim Cox in Fuck Yes Dude!</h2>
Read the Article
</div>
<img src="img/content/1.jpg" class="carousel__image" />
</div>
And the javascript that gets the image URL and adds it to the page is this:
$(function() {
var overlay = $('.carousel__bg img'), cached = {};
$('.carousel__item').mouseenter(function() {
var item = $(this),
spot = $(this).index('.carousel__item'),
value = item.attr('data-src');
overlay.fadeTo(0,0).attr('src', value);
if (!overlay[0].complete && !cached[spot]) {
cached[spot] = true;
$('.carousel__bg').addClass('loading');
overlay.one('load', function() {
$('.carousel__bg').removeClass('loading');
overlay.fadeTo(300,1);
});
}
else overlay.fadeTo(300,1);
})
.mouseleave(function() {
overlay.finish();
});
});
Obviously the problem is if I specify data-src="video/safari.mp4" it isn't going to work as it's currently trying to add the video into an img element. So how would I go about switching between img/video tags? A related issue would be to be able to load both an mp4 + webm/ogg versions of the file?
So would it need to be reworked to 'inject' an img or video element onto the page depending on the extension? I tried using an if/else statement to check if the data-src contained the .mp4 extension and just hardcoded a video element on the page to text but couldn't get that to work. :/
These files can be quite large which is why I'm not loading them until they're needed.
Edit
As a bit of an aside, I decided to put these items in a carousel to see if this effect would work - and it pretty much does!
However, I noticed the way that I fade out the images in the CSS (fade all of them out when the .carousel is hovered but then target the individual item and overwrite) is now a problem when you hover over the prev/next buttons as the images don't fade back in.
Anyone got a better way of handling this? I tried a 100% CSS method but maybe added a class would be better?
Slick carousel example: https://codepen.io/moy/pen/JjdvRyG
The video element part is not two hard, the important part is getting the mime type of the video to add to the source element.
The data-src takes an array of video urls (of different types) and adds the different sources to the element after finding the type.
I updated your codepen
As for the buttons, they are inside the .carousel element so the will bubble the hover to all the elements styled based on that. I made some elements more specific so they will only change style when the list of items is hovered.
Finally, in order for the listeners to apply to the slick element, I changed them to .on.
var VIDEO_TYPES = {
'mp4': 'video/mp4',
'webm': 'video/webm',
'ogv': 'video/ogg',
}
/**
* Slick
*/
$(document).ready(function() {
$('.slick-carousel').slick({
//centerMode: true,
centerPadding: '0',
slidesToShow: 3,
arrows: true,
dots: false,
prevArrow: '<a class="slick-arrow slick-arrow--prev"><span>←</span></a>',
nextArrow: '<a class="slick-arrow slick-arrow--next"><span>→</span></a>',
responsive: [{
breakpoint: 960,
settings: {
centerMode: true,
slidesToShow: 1
}
},
{
breakpoint: 600,
settings: {
centerMode: true,
slidesToShow: 1
}
},
{
breakpoint: 480,
settings: {
centerMode: true,
slidesToShow: 1
}
}
]
})
.on('setPosition', function(event, slick) {
slick.$slider.find(".slick-slide .tile:not(.position-set)").addClass('position-set').css('height', slick.$slideTrack.height() - 30 + 'px');
});
/**
* Image Swap
*/
var cached = {};
var overlay_video = $(".carousel__bg video");
var overlay_img = $(".carousel__bg img");
var overlay = $(".carousel__bg");
$(".carousel__item")
.on('mouseenter', function() {
var item = $(this),
spot = $(this).index(".carousel__item"),
value = item.data("src");
overlay_video.empty();
var overlay_item;
overlay.fadeTo(0, 0);
//videos will have an array ur urls
var is_video = value instanceof Array;
if(is_video) {
overlay_item = overlay_video;
overlay_img.attr("src", '');
overlay_video.append(value.map((url) => {
var extension = url.split('.').pop();
var type = VIDEO_TYPES[extension];
return `<source src="${url}" type="${type}">`
}));
} else {
overlay_item = overlay_img;
overlay_img.attr("src", value);
}
//force the video element to reload
overlay_video.get(0).load();
if (!overlay_item.complete && !cached[spot]) {
cached[spot] = true;
overlay.addClass("loading");
overlay_item.one(is_video ? "loadeddata" : "load", function() {
overlay.removeClass("loading");
overlay.fadeTo(300, 1);
});
} else overlay.fadeTo(300, 1);
})
.on('mouseleave', function() {
overlay.finish();
});
});
/**
* Base styling.
*/
html {
background: rgb(255,255,255);
font-size: 62.5%;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-overflow-scrolling: touch;
-webkit-text-size-adjust: 100%;
}
body {
background-color: transparent;
color: rgb(0,0,0);
font-variant-ligatures: common-ligatures discretionary-ligatures historical-ligatures;
font-family: 'Roboto', sans-serif;
font-size: 1.6rem;
font-weight: 400;
line-height: 1.6rem;
margin: 0;
padding: 30px 0 0;
text-rendering: optimizeLegibility;
}
/**
* Carousel
*/
.carousel {
background: rgb(0,0,0);
color: rgb(255,255,255);
height: 640px;
margin: 0 auto;
overflow: hidden;
position: relative;
width: 100%;
max-width: 1200px;
}
.carousel:before,
.carousel:after {
background: rgba(255,255,255,.25);
content: "";
height: 100%;
position: absolute;
top: 0;
left: 33.33333%;
width: 1px;
z-index: 30;
}
.carousel:after {
left: 66.66666%;
}
/**
* Background (fullwidth) image
*/
.carousel__bg {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
height: 100%;
width: 100%;
}
.carousel__bg.loading {
background: url(../img/interface/loading.gif) no-repeat center center;
}
.carousel__bg img, .carousel__bg video {
display: block;
height: 640px;
object-fit: cover;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
}
/**
* Individual carousel item
*/
.carousel__item {
box-sizing: border-box;
float: left;
height: 640px;
position: relative;
width: 33.33333%;
}
.carousel__item:hover {
cursor: pointer;
}
/* Text Content */
.carousel__content {
background: rgba(0,0,0,.45);
box-sizing: border-box;
color: rgb(255,255,255);
height: 100%;
min-height: 100%;
padding: 30px;
position: absolute;
top: 0;
left: 0;
width: 100%;
z-index: 15;
}
.carousel__title,
.carousel__subtitle,
.carousel__flag {
color: rgb(255,255,255);
letter-spacing: 1px;
font-family: 'Anton', sans-serif;
font-weight: 400;
line-height: 1;
margin: 0 0 5px;
padding: 0;
text-transform: uppercase;
}
.carousel__title {
font-size: 20px;
transition: all .25s;
}
.carousel__subtitle {
display: none;
font-size: 48px;
}
.carousel__flag {
color: rgb(45,190,193);
font-size: 14px;
}
/* Button */
.carousel__btn {
background: transparent;
border: 1px solid rgb(255,255,255);
box-sizing: border-box;
color: rgb(255,255,255);
display: block;
font-family: 'Anton', sans-serif;
font-size: 12px;
font-weight: 400;
height: 45px;
line-height: 45px;
letter-spacing: 1px;
opacity: 0;
position: absolute;
padding: 0 30px;
bottom: 30px;
left: 30px;
right: 30px;
text-align: center;
text-decoration: none;
text-transform: uppercase;
transition: all .15s;
-webkit-backface-visibility: hidden;
}
.carousel__btn:visited {
background: transparent;
}
.carousel__btn:focus,
.carousel__btn:hover {
background: rgb(45,190,193);
border-color: rgb(45,190,193);
}
/* Image */
.carousel__image {
display: block;
height: 100%;
opacity: 1;
object-fit: cover;
transition: all .30s;
position: relative;
width: 100%;
max-width: 100%;
-webkit-backface-visibility: hidden;
}
/* When hovering over the carousel, fade all the titles out */
.carousel>.slick-carousel>.slick-list:hover .carousel__title {
opacity: .30;
}
/* But not the one contained without the 'item' you're hovering over */
.carousel:hover .carousel__item:hover .carousel__title {
opacity: 1;
}
/* Fade all images out so the fullwidth background image is visble */
.carousel>.slick-carousel>.slick-list:hover .carousel__image {
opacity: 0;
}
/* Hide the flag element */
.carousel>.slick-carousel>.slick-list:hover .carousel__flag {
display: none;
}
/* Show the subtitle */
.carousel:hover .carousel__item:hover .carousel__subtitle {
display: block;
}
/* Display the CTA of the active item */
.carousel:hover .carousel__item:hover .carousel__btn {
opacity: 1;
}
/* Slick Prev/Next */
.slick-carousel,
.slick-list,
.slick-track {
height: 100%;
min-height: 100%;
}
.slick-arrow {
background: transparent;
border: 1px solid rgb(255,255,255);
color: rgb(255,255,255);
display: block;
font-family: 'Anton', sans-serif;
font-size: 24px;
height: 45px;
line-height: 45px;
margin-top: -30px;
overflow: hidden;
position: absolute;
top: 50%;
left: 30px;
text-align: center;
transform: rotate(45deg);
transition: all .15s;
width: 45px;
z-index: 60;
}
.slick-arrow:hover {
background: rgb(255,255,255);
color: rgb(0,0,0);
}
.slick-arrow span {
display: block;
transform: rotate(-45deg);
}
.slick-arrow--next {
left: auto;
right: 30px;
}
/* Slick Core */
.slick-slider
{
position: relative;
display: block;
box-sizing: border-box;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-touch-callout: none;
-khtml-user-select: none;
-ms-touch-action: pan-y;
touch-action: pan-y;
-webkit-tap-highlight-color: transparent;
}
.slick-list
{
position: relative;
display: block;
overflow: hidden;
margin: 0;
padding: 0;
}
.slick-list:focus
{
outline: none;
}
.slick-list.dragging
{
cursor: pointer;
cursor: hand;
}
.slick-slider .slick-track,
.slick-slider .slick-list
{
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.slick-track
{
position: relative;
top: 0;
left: 0;
display: block;
margin-left: auto;
margin-right: auto;
}
.slick-track:before,
.slick-track:after
{
display: table;
content: '';
}
.slick-track:after
{
clear: both;
}
.slick-loading .slick-track
{
visibility: hidden;
}
.slick-slide
{
display: none;
float: left;
height: 100%;
min-height: 1px;
}
[dir='rtl'] .slick-slide
{
float: right;
}
.slick-slide img
{
display: block;
}
.slick-slide.slick-loading img
{
display: none;
}
.slick-slide.dragging img
{
pointer-events: none;
}
.slick-initialized .slick-slide
{
display: block;
}
.slick-loading .slick-slide
{
visibility: hidden;
}
.slick-vertical .slick-slide
{
display: block;
height: auto;
border: 1px solid transparent;
}
.slick-arrow.slick-hidden {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/slick-carousel/1.9.0/slick.min.js"></script>
<div class="carousel">
<div class="carousel__bg">
<img src="" />
<video autoplay muted loop></video>
</div>
<div class="slick-carousel">
<div class="carousel__item" data-src="https://www.fillmurray.com/750/550">
<div class="carousel__content">
<h4 class="carousel__title">Behind The Scenes</h4>
<span class="carousel__flag">// Featured</span>
<h2 class="carousel__subtitle">Lorem ipsum dolor</h2>
Read the Article
</div>
<img src="https://www.fillmurray.com/g/400/600" class="carousel__image" />
</div>
<div class="carousel__item" data-src="https://www.fillmurray.com/800/600">
<div class="carousel__content">
<h4 class="carousel__title">Reed Stark</h4>
<span class="carousel__flag">// Featured</span>
<h2 class="carousel__subtitle">Lorem ipsum dolor</h2>
Watch the Video
</div>
<img src="https://www.fillmurray.com/g/450/650" class="carousel__image" />
</div>
<div class="carousel__item" data-src='[ "https://www.w3schools.com/tags/movie.mp4", "https://www.w3schools.com/tags/movie.ogg"]'>
<div class="carousel__content">
<h4 class="carousel__title">Fresh Drops</h4>
<span class="carousel__flag">// Featured</span>
<h2 class="carousel__subtitle">Lorem ipsum dolor</h2>
See The Collection
</div>
<img src="https://www.fillmurray.com/g/350/550" class="carousel__image" />
</div>
<div class="carousel__item" data-src='[ "https://www.w3schools.com/tags/movie.mp4", "https://www.w3schools.com/tags/movie.ogg"]'>
<div class="carousel__content">
<h4 class="carousel__title">Fresh Drops</h4>
<span class="carousel__flag">// Featured</span>
<h2 class="carousel__subtitle">Lorem ipsum dolor</h2>
See The Collection
</div>
<img src="https://www.fillmurray.com/g/300/500" class="carousel__image" />
</div>
</div>
</div>
Related
I have two modals, left and right, each drop down when clicked and want to have only one toggle appear as an on/off when activated.
Right now, both toggles appear when either modal is on. When the LEFT toggle is on and the modal drops down I want to hide the RIGHT toggle button and modal (and vice versa).
// common close button
$('.toggle').click(function() {
$(this).closest(".modal").toggleClass('modal-visible');
});
// explicit button per modal
$('.toggle').on('click', function(e) {
var modalid = $(this).data("modal-id");
$(`.modal[data-modal-id='${modalid}']`).toggleClass('modal-visible');
});
.modal {
position: fixed;
z-index: 10000;
/* 1 */
top: 0;
left: 0;
visibility: hidden;
width: 100%;
height: 100%;
box-sizing: border-box;
}
.modal.modal-visible {
visibility: visible;
}
.modal-overlay {
position: fixed;
z-index: 10;
top: 0;
left: 0;
width: 100%;
height: 0%;
background: #fff;
visibility: hidden;
opacity: 0;
transition: visibility 0s height 0.5s;
box-sizing: border-box;
}
.modal.modal-visible .modal-overlay {
opacity: 1;
visibility: visible;
transition-delay: 0s;
}
.modal-wrapper {
position: fixed;
z-index: 9999;
top: 0;
left: 0;
width: 100%;
height: 100%;
margin-left: 0;
background-color: #fff;
box-sizing: border-box;
}
.modal-transition {
transition: all 0.5s;
transform: translateY(-100%);
opacity: 1;
}
.modal.modal-visible .modal-transition {
transform: translateY(0);
opacity: 1;
}
.modal-header,
.modal-content {
padding: 1em;
}
.modal-header {
position: relative;
top: 10%;
background-color: #fff;
}
.modal-close {
position: fixed;
top: 0;
right: 0;
padding: 1em;
color: #aaa;
background: none;
border: 0;
font-size: 18px;
}
.modal-close:hover {
color: #777;
}
.modal-heading {
font-size: 1.125em;
margin: 0;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.modal-content>*:first-child {
margin-top: 0;
}
.modal-content>*:last-child {
margin-bottom: 0;
}
.modal.modal-scroll .modal-content {
max-height: 100%;
overflow-y: scroll;
}
.modal.modal-scroll .modal-wrapper {
position: absolute;
z-index: 9999;
top: 2em;
left: 50%;
width: 32em;
margin-left: -16em;
background-color: #CDf;
box-shadow: 0 0 1.5em hsla(0, 0%, 0%, 0.35);
box-sizing: border-box;
}
button {
background: transparent;
font-family: 'Republique', sans-serif;
font-variant: normal;
font-weight: 400;
font-size: 24px;
line-height: 0.5;
-webkit-hyphens: auto;
-moz-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
letter-spacing: .4px;
color: #000;
cursor: pointer;
outline: 0;
border: 0;
padding: 4px;
}
#righty {
position: fixed;
right: 10px;
top: 10px;
z-index: 100000;
}
#lefty {
position: fixed;
left: 10px;
top: 10px;
z-index: 100000;
}
body {
background: pink;
}
button {
color: white;
}
button:hover {
color: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="toggle" data-modal-id="lefty" id="lefty">LEFT</button>
<button class="toggle" data-modal-id="righty" id="righty">RIGHT</button>
<div class="modal" data-modal-id="lefty">
<div class="modal-overlay toggle"></div>
<div class="modal-wrapper modal-transition">
<div class="modal-header">
<button class="modal-close toggle"></button>
<h2 class="modal-heading">This is a modal on the left</h2>
</div>
<div class="modal-body">
<div class="modal-content">
</div>
</div>
</div>
</div>
<div class="modal" data-modal-id="righty">
<div class="modal-overlay toggle"></div>
<div class="modal-wrapper modal-transition">
<div class="modal-header">
<h2 class="modal-heading">This is a modal on the right</h2>
</div>
<div class="modal-body">
<div class="modal-content">
</div>
</div>
</div>
</div>
I tried various routes in CSS (nested divs, display:none, etc.) and struggling to find a solution. My javascript knowledge is very rudimentary, so perhaps there is a path there?
I added 4 lines in your JS:
We will declare 2 variables, one that will take the button's id (and therefore the modal id as well), and the other one, the id of the current visible modal.
We will then check if the two id are not matching, if it is true (meaning the id aren't the same) then we hide the visible modal by removing its class modal-visible.
If the two id are the same then we skip this step.
Lastly, we will toggle the modal with the button's id, it will either close it or open it.
That's all.
// common close button
$('.toggle').click(function() {
$(this).closest(".modal").toggleClass('modal-visible');
});
// explicit button per modal
$('.toggle').on('click', function(e) {
var modalid = $(this).data("modal-id");
var visible = $('.modal-visible').data("modal-id");
//check if the IDs are not the same
if (visible != modalid) {
$('.modal-visible').removeClass('modal-visible');
}
$(`.modal[data-modal-id='${modalid}']`).toggleClass('modal-visible');
});
I have a gallery that will open a modal when you click on an image or video. I am now trying to implement a previous and next button. I've been unable to get it working completely, I can only get it to display ONLY the previous image/video that the user initially clicked. I cannot get it to continually display the previous or after images/videos.
I feel like some sort of loop could do the trick, but I personally couldn't figure out the condition of a loop in order for it to loop properly.
Here is a https://jsfiddle.net/Boros/r9nsyw0m/
If you click on any image or video itself(not the play button), then click the previous arrow, you will see it displays the correct previous image/video. However, if you try to press the previous button again, nothing happens. Another issue is the next button doesn't even work. I have no idea why since it should be the exact same code as the previous button except it just adds one to the index instead of subtracting one like the previous button code. You may need to refresh after closing the modal after you clicked the previous button since it will display the incorrect image/video if you re-open the modal.
Line 50: Previous button
$("#previous").addEventListener("click", evt => {
slides[g].style.display = "none";
slides[g - 1].style.display = "initial";
});
Line 55: Next button
$("#next").addEventListener("click", evt => {
slides[g].style.display = "none";
slides[g + 1].style.display = "initial";
});
I've been learning JS for a couple months now so the code might be all over the place but I am happy I was able to get this far on this project.
I had a little look at the newer version of the code and whilst it is better it still has issues - the main being that the navigation still does not work. There appears to be a lot of repetition within the various parts of the code and I ended up approaching from a different direction to achieve what I hope was the stated goal. I may not have implemented all the things I see in the original - such as removing the tabindex attributes or other such. I also could not understand why there is duplication of the images/videos on the page other than to provide content for the modal - so these items were removed explicitly from the modal so that they can be copied/cloned later when actually needed.
(function(){
'use strict';
let index;
const d=document;
const q=(e,n=d)=>n.querySelector(e);
const qa=(e,n=d)=>n.querySelectorAll(e);
const col=qa('#gallery img,#gallery video');
const _length=col.length-1;
const modal=q('#my_modal');
const receiver=q('.receiver',modal);
const setdisplay=(n,s)=>n.style.display=s;
const setoverflow=(n,s)=>n.style.overflow=s;
const setindex=(i)=>qa('[data-type="nav"]').forEach(n=>n.dataset.index=i);
const pausevideos=()=>qa('video').forEach(n=>n.pause());
const clearstyle=(c)=>qa('[data-type="nav"]').forEach(n=>n.classList.remove(c));
const warn=(e,a,b,c)=>{
clearstyle(c);
if( a==b )e.target.classList.add(c)
};
const setinitialstate=(i,c)=>{
clearstyle(c);
if( i==0 )q('[data-task="prev"]').classList.add(c)
if( i==_length )q('[data-task="next"]').classList.add(c)
}
const _CN='red';
/*
Define all the event handlers for
the modal buttons etc
*/
const closeclickhandler=(e)=>{
receiver.innerHTML='';
pausevideos();
setdisplay(modal,'none');
setoverflow(d.body,'initial');
return true;
};
/*
The prev/next handlers could be a single function
that processes the dataset to fork the logic within.
Find the index from the button and use that to determine
and display the next/prev item. The `setcontent` function
takes the item and clones it so it can be displayed.
*/
const previousclickhandler=(e)=>{
index=e.target.dataset.index;
if( index > 0 ){
index--;
warn(e,index,0,_CN);
setindex(index);
setcontent(col[index]);
}
return true;
};
const nextclickhandler=(e)=>{
index=e.target.dataset.index;
if( index < _length){
index++;
warn(e,index,_length,_CN);
setindex(index);
setcontent(col[index])
}
return true;
};
const bttnclickhandler=(e)=>{
/*
This is a `delegated` event handler
bound to the modal but operating
only on elements with a data-task
attribute.
*/
switch( e.target.dataset.task ){
case 'close': return closeclickhandler(e);
case 'prev': return previousclickhandler(e);
case 'next': return nextclickhandler(e);
}
};
/*
assign initial slide to the modal and
then set the index to the navigation
buttons.
*/
const slideclickhandler=(e)=>{
setcontent(e.target);
setindex(e.target.dataset.index);
setinitialstate(e.target.dataset.index,_CN);
};
const keyuphandler=(e)=>{
/* close modal if the user presses the ESC/Enter key */
if( e.keyCode == 27 || e.keyCode == 13 )closeclickhandler.call(this,e);
};
const setcontent=(item)=>{
let clone=item.cloneNode(true);
let div=d.createElement('div');
div.className=clone instanceof HTMLImageElement ? 'img_slides' : 'video_slides';
div.append( clone );
if( clone instanceof HTMLVideoElement ){
div.append( item.nextElementSibling.cloneNode( true ) );
clone.controls=true;
clone.muted=true;
}
receiver.innerHTML='';
receiver.appendChild( div );
setdisplay(div,'initial');
setdisplay(modal,'initial');
};
/*
Assign all the listeners
*/
col.forEach((n,i)=>{
n.dataset.index=i; // !!important!!
n.setAttribute( 'alt', n.src.split('/').pop() );
n.addEventListener('click',slideclickhandler);
});
modal.addEventListener('click',bttnclickhandler);
d.addEventListener('keyup',keyuphandler);
})();
* { box-sizing: border-box; }
html {
font-family: Arial, Helvetica, sans-serif;
margin: 0;
padding: 0;
color: white;
font-size: 16px;
background-color: black;
}
#gallery {
text-align: center;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#gallery img, video {
width: 100%;
max-width: 360px;
height: 480px;
object-fit: cover;
cursor: pointer;
image-rendering: -webkit-optimize-contrast;
}
.video_container {
position: relative;
display: inline-block;
width: 100%;
max-width: 360px;
height: 480px;
margin: 0;
padding: 0;
cursor: pointer;
}
/* Prevents video from moving when hovered on chrome */
.video_container video {
filter: brightness(1);
}
.fa-play {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
cursor: pointer;
font-size: 2rem;
color: white;
}
#gallery img:hover, .video_container:hover {
transition: opacity 0.3s;
opacity: 0.8;
}
.fa-play:hover {
transition: color 0.5s;
color: #181818;
}
#keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
#keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
#my_modal {
animation-name: fadeIn;
animation-duration: 0.5s;
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
overflow: auto;
margin: 0;
padding: 0;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
.img_slides,
.video_slides {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
.img_slides img {
max-height: 100%;
max-width: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
object-fit: contain;
image-rendering: -webkit-optimize-contrast;
}
.video_slides video{
height: auto;
max-height: 100%;
width: auto;
max-width: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
object-fit: contain;
image-rendering: -webkit-optimize-contrast;
}
#close_button,
[data-task='close']{
cursor: pointer;
text-align: center;
font-size: 4rem;
width: 4rem;
position: absolute;
right: 0;
border-radius: 16px;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#previous,
[data-task='prev']{
cursor: pointer;
text-align: center;
font-size: 3rem;
width: 4rem;
position: absolute;
left: 0;
bottom: 0;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#next,
[data-task='next']{
cursor: pointer;
text-align: center;
font-size: 3rem;
width: 4rem;
position: absolute;
right: 0;
bottom: 0;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#close_button:hover,
[data-task='close']:hover{
transition: opacity 0.1s;
opacity: 0.5;
}
#previous:hover,
[data-task='prev']:hover{
transition: opacity 0.1s;
opacity: 0.5;
}
#next:hover,
[data-task='next']:hover{
transition: opacity 0.1s;
opacity: 0.5;
}
/* new */
.receiver{
display:flex;
flex-direction:column;
align-content:center;
align-items:center;
justify-content:center;
}
.receiver img,
.receiver video{
margin:auto
}
.red{
color:red;
}
[data-char]:after{
content:attr(data-char)
}
<div id='gallery'>
<img src='//i.imgur.com/gyVTo26.jpg' alt='' tabindex='1' />
<img src='//i.imgur.com/bEo04qh.jpg' alt='' tabindex='1' />
<img src='//i.imgur.com/iRENtzp.jpg' alt='' tabindex='1' />
<img src='//i.imgur.com/ElkQu54.jpg' alt='' tabindex='1' />
<img src='//i.imgur.com/Aj25iuv.jpg' alt='' tabindex='1' />
<div class='video_container'>
<video src='//i.imgur.com/kKGF9Az.mp4' tabindex='1' muted></video>
<i class='fas fa-play'></i>
</div>
<div class='video_container'>
<video src='//i.imgur.com/p7ohLnA.mp4' tabindex='1' muted></video>
<i class='fas fa-play'></i>
</div>
<img src='//i.imgur.com/PxWajo9.jpg' alt='' tabindex='1' />
<img src='//i.imgur.com/CAh7F8p.jpg' alt='' tabindex='1' />
</div>
<div id='my_modal'>
<div class='receiver'></div>
<span data-task='close' data-char='×' tabindex='0'></span>
<span data-task='prev' data-char='<' data-type='nav' tabindex='0'></span>
<span data-task='next' data-char='>' data-type='nav' tabindex='0'></span>
</div>
Update
Following from your comments regarding beginner status and still learning I worked a similar solution to that I proposed before but without the cloneNode approach and without modifying your HTML structure at all (apart from removing the scheme from image/video urls )
"use strict";
let index;
const d=document;
const body=d.body;
const q=(e,n=d)=>n.querySelector(e);
const qa=(e,n=d)=>n.querySelectorAll(e);
let modal=q('#my_modal');
let gallery=q('#gallery');
let bttns=qa('span',modal);
let videos=qa('video');
let collection=qa('[tabindex="1"]',gallery);
let items=qa('div[ class$="_slides" ]',modal);
let _length=items.length - 1;
const setdisplay=(nodes,style)=>{
if( nodes instanceof Array || nodes instanceof NodeList )nodes.forEach(n=>n.style.display=style);
else if( nodes instanceof HTMLElement )nodes.style.display=style;
};
const setoverflow=(n,value)=>n.style.overflow=value;
const setattribs=(col,attr,value)=>col.forEach(n=>n.setAttribute(attr,value));
const pausevideos=(col)=>col.forEach(n=>n.pause());
const removetabs=(col)=>col.forEach(n=>n.removeAttribute('tabindex'));
const setindices=(col,i)=>col.forEach(n=>n.dataset.index=i);
const closeModal = e => {
if ( e.target == q('#close_button') || e.keyCode==27 || e.keyCode==13 ) {
setoverflow(body,'initial')
setdisplay(modal,'none');
setdisplay(items,'none');
setattribs(collection,'tabindex',1);
pausevideos(videos);
}
};
const bttnclickhandler=(e)=>{
switch(e.target.id){
case 'previous':
if( index > 0 )index--;
break;
case 'next':
if( index < _length )index++;
break;
}
setindices(bttns,index);
setdisplay(items,'none');
setdisplay(items[index],'initial');
return true;
}
// set the dataset attribute on all items within modal & gallery
qa('#gallery > *').forEach((n,i)=>n.dataset.index=i);
qa('#my_modal > *').forEach((n,i)=>n.dataset.index=i);
// assign event listener to each item in the gallery which displays
// that item & sets the global index.
qa('img,div',gallery).forEach( n=>n.addEventListener('click',function(e){
// Find which index the clicked item has and set the global index variable
index=Number( this.dataset.index );
// Find the respective item from the modal collection of nodes
let item=items[index];
// set properties
setdisplay(modal,'initial');
setdisplay(item,'initial');
setindices(bttns,index);
removetabs(collection);
}));
bttns.forEach(bttn=>bttn.addEventListener('click',e=>{
switch( e.target.id ){
case 'close_button':return closeModal(e);
default: return bttnclickhandler(e);
}
}));
d.addEventListener( 'keyup', closeModal );
* { box-sizing: border-box; }
html {
font-family: Arial, Helvetica, sans-serif;
margin: 0;
padding: 0;
color: white;
font-size: 16px;
background-color: black;
}
#gallery {
text-align: center;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#gallery img, video {
width: 100%;
max-width: 360px;
height: 480px;
object-fit: cover;
cursor: pointer;
image-rendering: -webkit-optimize-contrast;
}
.video_container {
position: relative;
display: inline-block;
width: 100%;
max-width: 360px;
height: 480px;
margin: 0;
padding: 0;
cursor: pointer;
}
/* Prevents video from moving when hovered on chrome */
.video_container video {
filter: brightness(1);
}
.fa-play {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
cursor: pointer;
font-size: 2rem;
color: white;
}
#gallery img:hover, .video_container:hover {
transition: opacity 0.3s;
opacity: 0.8;
}
.fa-play:hover {
transition: color 0.5s;
color: #181818;
}
#keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
#keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
#my_modal {
animation-name: fadeIn;
animation-duration: 0.5s;
display: none;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 9999;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4);
overflow: auto;
margin: 0;
padding: 0;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
.img_slides, .video_slides {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
padding: 0;
margin: 0;
width: 100%;
height: 100%;
}
.img_slides img {
max-height: 100%;
max-width: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
object-fit: contain;
image-rendering: -webkit-optimize-contrast;
}
.video_slides video{
height: auto;
max-height: 100%;
width: auto;
max-width: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
object-fit: contain;
image-rendering: -webkit-optimize-contrast;
}
#close_button {
cursor: pointer;
text-align: center;
font-size: 4rem;
width: 4rem;
position: absolute;
right: 0;
border-radius: 16px;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#previous {
cursor: pointer;
text-align: center;
font-size: 3rem;
width: 4rem;
position: absolute;
left: 0;
bottom: 0;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#next {
cursor: pointer;
text-align: center;
font-size: 3rem;
width: 4rem;
position: absolute;
right: 0;
bottom: 0;
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select:none;
user-select:none;
}
#close_button:hover {
transition: opacity 0.1s;
opacity: 0.5;
}
#previous:hover {
transition: opacity 0.1s;
opacity: 0.5;
}
#next:hover {
transition: opacity 0.1s;
opacity: 0.5;
}
<div id="gallery">
<img src="//i.imgur.com/gyVTo26.jpg" alt="" tabindex="1">
<img src="//i.imgur.com/bEo04qh.jpg" alt="" tabindex="1">
<img src="//i.imgur.com/iRENtzp.jpg" alt="" tabindex="1">
<img src="//i.imgur.com/ElkQu54.jpg" alt="" tabindex="1">
<img src="//i.imgur.com/Aj25iuv.jpg" alt="" tabindex="1">
<div class="video_container">
<video src="//i.imgur.com/kKGF9Az.mp4" tabindex="1" muted></video>
<i class="fas fa-play"></i>
</div>
<div class="video_container">
<video src="//i.imgur.com/p7ohLnA.mp4" tabindex="1" muted></video>
<i class="fas fa-play"></i>
</div>
<img src="//i.imgur.com/PxWajo9.jpg" alt="" tabindex="1">
<img src="//i.imgur.com/CAh7F8p.jpg" alt="" tabindex="1">
</div>
<div id="my_modal">
<div class="img_slides">
<img src="//i.imgur.com/gyVTo26.jpg" alt="">
</div>
<div class="img_slides">
<img src="//i.imgur.com/bEo04qh.jpg" alt="">
</div>
<div class="img_slides">
<img src="//i.imgur.com/iRENtzp.jpg" alt="">
</div>
<div class="img_slides">
<img src="//i.imgur.com/ElkQu54.jpg" alt="">
</div>
<div class="img_slides">
<img src="//i.imgur.com/Aj25iuv.jpg" alt="">
</div>
<div class="video_slides">
<video src="//i.imgur.com/kKGF9Az.mp4" controls muted></video>
</div>
<div class="video_slides">
<video src="//i.imgur.com/p7ohLnA.mp4" controls muted></video>
</div>
<div class="img_slides">
<img src="//i.imgur.com/PxWajo9.jpg" alt="">
</div>
<div class="img_slides">
<img src="//i.imgur.com/CAh7F8p.jpg" alt="">
</div>
<span id="close_button" tabindex="0">×</span>
<span id="previous" tabindex="0"><</span>
<span id="next" tabindex="0">></span>
</div>
The idea remains the same in principal. Items within the gallery and items within the modal are assigned a data-index attribute when the page loads ( this could be done another way but this is, imo, easier & less cluttered )
The global index variable is changed according to whether the previous or next buttons is clicked and that new index value is used to select the item within the modal with that same data-index value. The buttons data-index attribute is changed to that new index value so that the next time a button is clicked the process can repeat. If the index is approaching the limits ( 0 or _length ) then the index remains unchanged so no error occurs trying to select an invalid index. Alternatively at that point the index could be reset to the opposite value perhaps so the process becomes cyclic - not tested though. Plus 1?
I am using bxslider, using a responsive design, multiple sliders and a popup window. The problem. I have the multiple sliders working and rescaling with browser size. The problem is with the popup. The popup cuts off the images.
Note: My javascript skills are very limited, so please explain as much as possible. Examples are always best for non-coders like me.
This post: Bxslider in a pop up div ... makes reference to the bx-viewport having a height of 0px (due to the fact that the initial image was hidden). So, the javascript tries to get the initial image size, but fails because no image was shown (no image = no image height). Once the second image is shown (due to the bxslider autoplay), the problem fixes itself.
I tried to use the solution on Bxslider in a pop up div but it didn't work with my code (it makes reference to monbxslider.js, which I do not use).
So, I see what is causing the problem ... but have no idea how to fix it. I've tried playing with the styles, but that doesn't work. Fixed height doesn't work, because each slider is different, and may have a different image. Below are snippets of my code....
Header Javascript info...
<link href="/js/jquery.bxslider.css" rel="stylesheet"></script>
<script type="text/javascript" src="/js/jquery.min.js"></script>
<script type="text/javascript" src="/js/jquery.bxslider.min.js"></script>
<!-- Popup Toggle -->
<script type="text/javascript">
function toggle_menu(id) {
var e = document.getElementById(id);
if (e.style.display == 'block') e.style.display = 'none';
else e.style.display = 'block';
}
</script>
Styles for Popup
[id^="popup-"], div[id*=" popup-"] {
display:none;
}
.window {
display:block;
background:white;
position:fixed;
top:0; left:0;
margin:50px 5% 0 5%;
width:90%;
z-index: 1001;
}
.window .close {
width: 22px; height: 22px; background: #000; border-radius: 50%; border: 3px solid #fff; display: block; text-align: center; color: #fff; text-decoration: none; position: absolute; top: -10px; right: -10px; z-index: 1002;}
.window .bx-viewport { min-height:200px !important; }
.window .bx-viewport ul li img { width:100% !important; padding:10px; }
.window .bx-viewport ul li { width:100% !important; }
.windowoverlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background:rgba(0,0,0,0.8);
opacity:0.8;
filter:alpha(opacity=80);
z-index: 1000;
}
BxSlider CSS
/**
* BxSlider v4.1.2 - Fully loaded, responsive content slider
* http://bxslider.com
*
* Written by: Steven Wanderski, 2014
* http://stevenwanderski.com
* (while drinking Belgian ales and listening to jazz)
*
* CEO and founder of bxCreative, LTD
* http://bxcreative.com
*/
/** RESET AND LAYOUT
===================================*/
.bx-wrapper {
position: relative;
margin: 0 auto;
padding: 0;
/* *zoom: 1; */
}
.bx-wrapper img {
max-width: 100%;
display: block;
}
/** THEME
===================================*/
.bx-wrapper .bx-viewport {
background: #fff;
/*fix other elements on the page moving (on Chrome)*/
-webkit-transform: translatez(0);
-moz-transform: translatez(0);
-ms-transform: translatez(0);
-o-transform: translatez(0);
transform: translatez(0);
}
.bx-wrapper .bx-pager,
.bx-wrapper .bx-controls-auto {
position: absolute;
bottom: -30px;
width: 100%;
}
/* LOADER */
.bx-wrapper .bx-loading {
min-height: 50px;
background: url(../images/bx_loader.gif) center center no-repeat #fff;
height: 100%;
width: 100%;
position: absolute;
top: 0;
left: 0;
z-index: 2000;
}
/* PAGER */
.bx-wrapper .bx-pager {
text-align: center;
font-size: .85em;
font-family: Arial;
font-weight: bold;
color:#999;
padding-top: 20px;
}
.bx-wrapper .bx-pager .bx-pager-item,
.bx-wrapper .bx-controls-auto .bx-controls-auto-item {
display: inline-block;
*zoom: 1;
*display: inline;
}
.bx-wrapper .bx-pager.bx-default-pager a {
background: #999;
text-indent: -9999px;
display: block;
width: 10px;
height: 10px;
margin: 0 5px;
outline: 0;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
}
.bx-wrapper .bx-pager.bx-default-pager a:hover,
.bx-wrapper .bx-pager.bx-default-pager a.active {
background: #FFF;
}
/* DIRECTION CONTROLS (NEXT / PREV) */
.bx-wrapper .bx-prev {
left: 10px;
background: url(../images/controls.png) no-repeat 0 -32px;
}
.bx-wrapper .bx-next {
right: 20px;
background: url(../images/controls.png) no-repeat -43px -32px;
}
.bx-wrapper .bx-prev:hover {
background-position: 0 0;
}
.bx-wrapper .bx-next:hover {
background-position: -43px 0;
}
.bx-wrapper .bx-controls-direction a {
position: absolute;
top: 50%;
margin-top: -16px;
outline: 0;
width: 33px;
height: 31px;
text-indent: -9999px;
z-index: 9999;
}
.bx-wrapper .bx-controls-direction a.disabled {
display: none;
}
/* AUTO CONTROLS (START / STOP) */
.bx-wrapper .bx-controls-auto {
text-align: center;
display:none; /*Hide Stop Button*/
}
.bx-wrapper .bx-controls-auto .bx-start {
display: block;
text-indent: -9999px;
width: 10px;
height: 11px;
outline: 0;
background: url(../images/controls.png) -86px -11px no-repeat;
margin: 0 3px;
}
.bx-wrapper .bx-controls-auto .bx-start:hover,
.bx-wrapper .bx-controls-auto .bx-start.active {
background-position: -86px 0;
}
.bx-wrapper .bx-controls-auto .bx-stop {
display: inline-block;
text-indent: -9999px;
width: 9px;
height: 11px;
outline: 0;
background: url(../images/controls.png) -86px -44px no-repeat;
margin: 0 3px;
}
.bx-wrapper .bx-controls-auto .bx-stop:hover,
.bx-wrapper .bx-controls-auto .bx-stop.active {
background-position: -86px -33px;
}
/* PAGER WITH AUTO-CONTROLS HYBRID LAYOUT */
.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-pager {
position:absolute;
bottom:10px;
text-align: center;
margin:0 auto;
}
.bx-wrapper .bx-controls.bx-has-controls-auto.bx-has-pager .bx-controls-auto {
right: 0;
width: 35px;
}
/* IMAGE CAPTIONS */
.bx-wrapper .bx-caption {
position: absolute;
bottom: 0;
left: 0;
background: #666\9;
background: rgba(80, 80, 80, 0.75);
width: 100%;
}
.bx-wrapper .bx-caption span {
color: #fff;
font-family: Arial;
display: block;
font-size: .85em;
padding: 10px;
}
HTML
<a href="javascript:void(0)" onclick="toggle_menu('popup-1">
<img src="/images/Feature1_300x300.jpg" alt="" />
</a>
<!-- Popup -->
<script type="text/javascript">
$(document).ready(function(){
$('#slider1').bxSlider({
mode: 'fade',
auto: true,
autoControls: true,
pause: 90000,
adaptiveHeight: true
});
});
</script>
<div class="popup" id="popup-1">
<div class="window">
<a href="#" onclick="toggle_menu('popup-1');">
<div class="close">X</div>
</a>
<!-- Slider -->
<ul id="slider1">
<li><img src="/images/Feature1.jpg" /></li>
<li><img src="/images/Feature2.jpg" /></li>
<li><img src="/images/Feature3.jpg" /></li>
</ul>
</div>
<div class="windowoverlay"></div>
</div>
<!-- Popup END -->
Here is the site. Scroll down and click the van image for the popup:
http://www.amazingdg.com/clients/testsite/
Right now the popup starts as display:none. I tried making the display visible, and positioned "off screen", and then "move" the popup onto the visible screen when it is clicked. However, the height was still not recognized. Anyone out there with some ideas?
Figure it out...
When I call the popup, I activate the slider when the popup is displayed (changing display:none to display:block). I was doing it before the popup was called, and that was where the problem was. So the image "height" is activated when the popup is activated, and then the slider is run.
<script type="text/javascript">
function popupwin(Id) {
var winname = document.getElementById(Id);
if (winname.style.display == 'block') {
winname.style.display = 'none';
} else {
winname.style.display = 'block';
$('#slider<?php echo $slidr; ?>').bxSlider({
mode: 'fade',
auto: true,
autoControls: true,
pause: 90000,
adaptiveHeight: true
});
}
}
</script>
I want to change the arrows in my slick slider but it does not change. I want the next and previous button as an image. I have tried putting it in a <style> but it still not working. Where can I change the arrows setting?
slick theme css
#charset "UTF-8";
// Default Variables
$slick-font-path: "./fonts/" !default;
$slick-font-family: "slick" !default;
$slick-loader-path: "./" !default;
$slick-arrow-color: white !default;
$slick-dot-color: black !default;
$slick-dot-color-active: $slick-dot-color !default;
$slick-prev-character: "←" !default;
$slick-next-character: "→" !default;
$slick-dot-character: "•" !default;
$slick-dot-size: 6px !default;
$slick-opacity-default: 0.75 !default;
$slick-opacity-on-hover: 1 !default;
$slick-opacity-not-active: 0.25 !default;
#function slick-image-url($url) {
#if function-exists(image-url) {
#return image-url($url);
}
#else {
#return url($slick-loader-path + $url);
}
}
#function slick-font-url($url) {
#if function-exists(font-url) {
#return font-url($url);
}
#else {
#return url($slick-font-path + $url);
}
}
/* Slider */
.slick-list {
.slick-loading & {
background: #fff slick-image-url("ajax-loader.gif") center center no-repeat;
}
position: absolute;
margin: 0 auto;
}
/* Icons */
#if $slick-font-family == "slick" {
#font-face {
font-family: "slick";
src: slick-font-url("slick.eot");
src: slick-font-url("slick.eot?#iefix") format("embedded-opentype"), slick-font-url("slick.woff") format("woff"), slick-font-url("slick.ttf") format("truetype"), slick-font-url("slick.svg#slick") format("svg");
font-weight: normal;
font-style: normal;
}
}
/* Arrows */
.slick-prev,
.slick-next {
position: absolute;
display: block;
height: 20px;
width: 30px;
line-height: 0px;
font-size: 0px;
cursor: pointer;
background: transparent;
color: transparent;
top: 50%;
margin-top: -10px;
padding: 0;
border: none;
outline: none;
&:hover, &:focus {
outline: none;
background: transparent;
color: transparent;
&:before {
opacity: $slick-opacity-on-hover;
}
}
&.slick-disabled:before {
opacity: $slick-opacity-not-active;
}
}
.slick-prev:before, .slick-next:before {
font-family: $slick-font-family;
font-size: 20px;
line-height: 1;
color: $slick-arrow-color;
opacity: $slick-opacity-default;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.slick-prev {
left: -25px;
[dir="rtl"] & {
left: auto;
right: -25px;
}
&:before {
content: $slick-prev-character;
[dir="rtl"] & {
content: $slick-next-character;
}
}
}
.slick-next {
right: -25px;
[dir="rtl"] & {
left: -25px;
right: auto;
}
&:before {
content: $slick-next-character;
[dir="rtl"] & {
content: $slick-prev-character;
}
}
}
/* Dots */
.slick-slider {
margin-bottom: 30px;
}
.slick-dots {
position: absolute;
bottom: -45px;
list-style: none;
display: block;
text-align: center;
padding: 0;
width: 100%;
li {
position: relative;
display: inline-block;
height: 20px;
width: 20px;
margin: 0 5px;
padding: 0;
cursor: pointer;
button {
border: 0;
background: transparent;
display: block;
height: 20px;
width: 20px;
outline: none;
line-height: 0px;
font-size: 0px;
color: transparent;
padding: 5px;
cursor: pointer;
&:hover, &:focus {
outline: none;
&:before {
opacity: $slick-opacity-on-hover;
}
}
&:before {
position: absolute;
top: 0;
left: 0;
content: $slick-dot-character;
width: 20px;
height: 20px;
font-family: $slick-font-family;
font-size: $slick-dot-size;
line-height: 20px;
text-align: center;
color: $slick-dot-color;
opacity: $slick-opacity-not-active;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
&.slick-active button:before {
color: $slick-dot-color-active;
opacity: $slick-opacity-default;
}
}
}
slick css
/* Slider */
.slick-slider {
position: relative;
margin: 0 auto;
display: block;
box-sizing: border-box;
-moz-box-sizing: border-box;
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-ms-touch-action: pan-y;
touch-action: pan-y;
-webkit-tap-highlight-color: transparent;
}
.slick-list {
position: relative;
overflow: hidden;
display: block;
margin: 0 auto;
padding: 0;
&:focus {
outline: none;
}
&.dragging {
cursor: pointer;
cursor: hand;
}
}
.slick-slider .slick-track,
.slick-slider .slick-list {
-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
-o-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
}
.slick-track {
position: relative;
left: 0;
top: 0;
display: block;
&:before,
&:after {
content: "";
display: table;
}
&:after {
clear: both;
}
.slick-loading & {
visibility: hidden;
}
}
.slick-slide {
float: left;
min-height: 1px;
[dir="rtl"] & {
float: right;
}
img {
display: block;
}
&.slick-loading img {
display: none;
}
display: none;
&.dragging img {
pointer-events: none;
}
.slick-initialized & {
display: block;
}
.slick-loading & {
visibility: hidden;
}
.slick-vertical & {
display: block;
height: auto;
border: 1px solid transparent;
}
}
preview of the site
Slick has a very easy way to customize its buttons through two variables in its own configuration: prevArrow and nextArrow.
Both types are: string (html | jQuery selector) | object (DOM node | jQuery object), so in your settings slick slider you can set the classes:
prevArrow: $('.prev')
nextArrow: $('.next')
and add to these elements the styles you want.
For example:
//HTML
<div class="slider-box _clearfix">
<div class="slick-slider">
<div>
<img src="img/home_carousel/home_carorusel_1.jpg">
</div>
<div>
<img src="img/home_carousel/home_carorusel_2.jpg">
</div>
<div>
<img src="img/home_carousel/home_carorusel_3.jpg">
</div>
<div>
<img src="img/home_carousel/home_carorusel_4.jpg">
</div>
</div>
</div>
<div class="paginator-center text-color text-center">
<h6>VER MAS LANZAMIENTOS</h6>
<ul>
<li class="prev"></li>
<li class="next"></li>
</ul>
</div>
//JS
$(document).ready(function () {
$('.slick-slider').slick({
centerMode: true,
centerPadding: '60px',
slidesToShow: 3,
prevArrow: $('.prev'),
nextArrow: $('.next'),
});
//CSS
.paginator{
position: relative;
float: right;
margin-bottom: 20px;
li{
margin-top: 20px;
position: relative;
float: left;
margin-right: 20px;
&.prev{
display: block;
height: 20px;
width: 20px;
background: url('../img/back.png') no-repeat;
}
&.next{
display: block;
height: 20px;
width: 20px;
background: url('../img/next.png') no-repeat;
}
}
}
You can easily create your own style of arrow with the .slick-next:before and the .slick-prev:after pseudo-classes.
Here's an example:
.slick-prev:before {
content: "<";
color: red;
font-size: 30px;
}
.slick-next:before {
content: ">";
color: red;
font-size: 30px;
}
its very easy. Use the bellow code, Its works for me. Here I have used fontawesome icon but you can use anything as image or any other Icon's code.
$(document).ready(function(){
$('.slider').slick({
autoplay:true,
arrows: true,
prevArrow:"<button type='button' class='slick-prev pull-left'><i class='fa fa-angle-left' aria-hidden='true'></i></button>",
nextArrow:"<button type='button' class='slick-next pull-right'><i class='fa fa-angle-right' aria-hidden='true'></i></button>"
});
});
This worked for me:
http://codepen.io/anon/pen/qNbWwK
Hide the default buttons in CSS and use:
<!-- In HTML: -->
<p class="left">left</p>
<p class="right">right</p>
/* In the JS file */
$('.slider').slick({
arrows: false
})
$('.left').click(function(){
$('.slider').slick('slickPrev');
})
$('.right').click(function(){
$('.slider').slick('slickNext');
})
Easy solution:
$('.slick-slider').slick({
arrows: true,
prevArrow:"<img class='a-left control-c prev slick-prev' src='YOUR LEFT ARROW IMAGE URL'>",
nextArrow:"<img class='a-right control-c next slick-next' src='YOUR RIGHT ARROW IMAGE URL'>"
});
Image URLs can be local or cdn-type stuff (web icons, etc.).
Example CSS (adjust as needed here, this is just an example of what's possible):
.control-c {
width: 30px;
height: 30px;
}
This worked well for me!
If you are using sass you can simply set below mentioned variables,
$slick-font-family:FontAwesome;
$slick-prev-character: "\f053";
$slick-next-character: "\f054";
These will change the font family used by slick's theme css and also the unicode for prev and next button.
Other sass variables which can be configured are given in Slick Github page
You can use FontAwesome "content" values and apply as follow by css. These apply "chevron right/left" icons.
.custom-slick .slick-prev:before {
content: "";
font-family: 'FontAwesome';
font-size: 22px;
}
.custom-slick .slick-next:before {
content: "";
font-family: 'FontAwesome';
font-size: 22px;
}
The Best way i Found to do that is this. You can remove my HTML and place yours there.
$('.home-banner-slider').slick({
dots: false,
infinite: true,
autoplay: true,
autoplaySpeed: 3000,
speed: 300,
slidesToScroll: 1,
arrows: true,
prevArrow: '<div class="slick-prev"><i class="fa fa-angle-left" aria-hidden="true"></i></div>',
nextArrow: '<div class="slick-next"><i class="fa fa-angle-right" aria-hidden="true"></i></div>'
});
<div class="prev">Prev</div>
<div class="next">Next</div>
$('.your_class').slick({
infinite: true,
speed: 300,
slidesToShow: 5,
slidesToScroll: 5,
arrows: true,
prevArrow: $('.prev'),
nextArrow: $('.next')
});
Add a value for prevArrow and nextArrow to change the standard arrows.
Example:
$('.members').slick({
slidesToShow: 1,
slidesToScroll: 1,
dots: true,
arrows: true,
prevArrow: '<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M20 40C8.9543 40 -2.7141e-06 31.0457 -1.74846e-06 20C-7.8281e-07 8.9543 8.95431 -2.7141e-06 20 -1.74846e-06C31.0457 -7.8281e-07 40 8.9543 40 20C40 31.0457 31.0457 40 20 40ZM16.1206 13.5198C15.7554 13.1055 15.1632 13.1055 14.798 13.5198L9.58704 19.4308C9.22182 19.8451 9.22182 20.5168 9.58704 20.931L14.798 26.8421C15.1632 27.2563 15.7554 27.2563 16.1206 26.8421C16.4858 26.4278 16.4858 25.7561 16.1206 25.3418L12.4912 21.2248L29.6865 21.2248C30.2388 21.2248 30.6865 20.7771 30.6865 20.2248C30.6865 19.6725 30.2388 19.2248 29.6865 19.2248L12.4138 19.2248L16.1206 15.02C16.4858 14.6057 16.4858 13.934 16.1206 13.5198Z" fill="#7C8B9C"/></svg>',
nextArrow: '<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M20 3.49691e-06C31.0457 5.4282e-06 40 8.95431 40 20C40 31.0457 31.0457 40 20 40C8.9543 40 1.56562e-06 31.0457 3.49691e-06 20C5.4282e-06 8.95431 8.95431 1.56562e-06 20 3.49691e-06ZM23.8794 26.4802C24.2446 26.8945 24.8368 26.8945 25.202 26.4802L30.413 20.5692C30.7782 20.1549 30.7782 19.4833 30.413 19.069L25.202 13.1579C24.8368 12.7437 24.2446 12.7437 23.8794 13.1579C23.5142 13.5722 23.5142 14.2439 23.8794 14.6582L27.5088 18.7752L10.3135 18.7752C9.7612 18.7752 9.31348 19.2229 9.31348 19.7752C9.31348 20.3275 9.76119 20.7752 10.3135 20.7752L27.5862 20.7752L23.8794 24.98C23.5142 25.3943 23.5142 26.066 23.8794 26.4802Z" fill="#7C8B9C"/></svg>',
});
Content property of pseudo element :before accepts images too. In slick-theme.css change:
// change
$slick-prev-character: "←" !default;
// to
$slick-prev-character: url('image-prev.png');
// and
$slick-next-character: "→" !default;
// to
$slick-next-character: url('image-next.jpg');
or directly change the content property on slick-prev:before and slick-next:before
.slick-prev {
left: -25px;
[dir="rtl"] & {
left: auto;
right: -25px;
}
&:before {
content: url('image-prev.jpg'); // <<<<<<<<
[dir="rtl"] & {
content: url('image-next.jpg'); // <<<<<<<<
}
}
}
.slick-next {
right: -25px;
[dir="rtl"] & {
left: -25px;
right: auto;
}
&:before {
content: url('image-next.jpg'); // <<<<<<<<
[dir="rtl"] & {
content: url('image-prev.jpg'); // <<<<<<<<
}
}
}
here is another example for changing the arrows and using your own arrow-images.
.slick-prev:before {
background-image: url('images/arrow-left.png');
background-size: 50px 50px;
display: inline-block;
width: 50px;
height: 50px;
content:"";
}
.slick-next:before {
background-image: url('images/arrow-right.png');
background-size: 50px 50px;
display: inline-block;
width: 50px;
height: 50px;
content:"";
}
Here's an alternative solution using javascipt:
document.querySelector('.slick-prev').innerHTML = '<img src="path/to/chevron-left-image.svg">'>;
document.querySelector('.slick-next').innerHTML = '<img src="path/to/chevron-right-image.svg">'>;
Change the img to text or what ever you require.
Here is my example of how to change the arrows for Slick Carousel in React to anything you would like. First you need to set the nextArrow and prevArrow in settings to a function then return a div in that function with whatever icon you would like to use. For mine I used Font Awesome. Then you will need to add a className in your icon, you will see that in the NextArrow and PrevArrow functions. Then add the scss code to customize whatever you would like.
JSX Code:
function NextArrow(props) {
const { style, onClick } = props;
return (
<div style={{ ...style, display: "block" }} onClick={onClick}>
<FontAwesomeIcon icon={faChevronRight} size="3x" className="slick-arrow-icon-right" />
</div>
);
}
function PrevArrow(props) {
const { style, onClick } = props;
return (
<div style={{ ...style, display: "block" }} onClick={onClick}>
<FontAwesomeIcon icon={faChevronLeft} size="3x" className="slick-arrow-icon-left" />
</div>
);
}
function SlickCarouselArrowChange(props) {
var settings = {
className: "slider variable-width",
dots: true,
infinite: true,
centerMode: true,
slidesToShow: 1,
slidesToScroll: 1,
variableWidth: true,
autoplay: true,
autoplaySpeed: 2000,
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
};
return (
<div className="slick-slider">
<Slider {...settings}>
{props.searchResults.map((image, index) => (
<div key={index}>
<img src={image.urls.small} />{" "}
</div>
))}
</Slider>
</div>
);
}
SCSS Code:
.slick-arrow-icon-left,
.slick-arrow-icon-right {
position: absolute;
display: block;
cursor: pointer;
background: transparent;
color: black;
top: 50%;
-webkit-transform: translate(0, -50%);
-ms-transform: translate(0, -50%);
transform: translate(0, -50%);
padding: 0;
border: none;
outline: none;
transition: 0.5s ease-in-out;
&:hover,
&:focus {
outline: none;
background: transparent;
color: black;
font-size: 40px;
&::before {
opacity: 1;
}
}
}
.slick-arrow-icon-left {
left: -50px;
[dir="rtl"] & {
left: auto;
right: -50px;
}
}
.slick-arrow-icon-right {
right: -50px;
[dir="rtl"] & {
left: -50px;
right: auto;
}
}
Example Link:
https://slick-carousel-arrow-change.herokuapp.com/
Source Code:
https://github.com/Apocilyptica/slick-carousel-arrow-change
For changing the color
.slick-prev:before {
color: some-color!important;
}
.slick-next:before {
color: some-color!important;
}
if your using react-slick you can try this on custom next and prev divs
https://react-slick.neostack.com/docs/example/previous-next-methods
If we want to use font awesome library using the css then we can use the below css
.slick-prev:before {
content: "\f104";
color: red;
font-size: 30px;
font-family: 'FontAwesome';
}
.slick-next:before {
content: "\f105";
color: red;
font-size: 30px;
font-family: 'FontAwesome';
}
Font awesome library css must be added in the page.
Hey there :) I'm trying to make a video fit the browser window size plus adding an image at the bottom of the browser window height. So you get the video and the image to be the only thing that is showed when you load the page. When you scroll dowm the content of the website should appear.
I've made something to illustrate the idea: http://instagib.dk/JS-test/
The problem is when I start adding the content of the site, it appears under video and image. The problem seems to be I've made it absolute and out of the documents context.
Is there any JS, Jquery solution that reads the height of the absolute content and places content after the video?
Cheers:)
<body>
<!-- Header -->
<header class="header">
<div class="header-bg">
<div class="logo-top"></div>
</div>
<nav>
<div class="menu">
<div class="hamburger"></div>
<div class="hamburger"></div>
<div class="hamburger"></div>
<ul class="nav-list">
<li>Projects</li>
<li>Services</li>
<li>Advantages</li>
<li>Who are we</li>
<li>Work with us</li>
</ul>
</div>
</nav>
</header>
<video class="intro" autoplay loop>
<source src="video/black_clouds.mp4" type="video/mp4">
<source src="video/black_clouds.webm" type="video/webm">
Your browser does not support the video tag.
</video>
<div class="intro-seperator"></div>
<!-- Main content -->
<main class="content">
</main>
<!-- Footer -->
<footer>
<small>© Crafthouse 2014</small>
</footer>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(function() {
divFade = $(".header-bg");
var toggleHeader = function(noAnimate) {
var threshold = 400,
fadeLength = 300,
opacity,
scrollTop = $(document).scrollTop();
if (scrollTop < threshold) {
opacity = 0;
} else if (scrollTop > threshold + fadeLength) {
opacity = 1;
} else {
if (noAnimate) {
opacity = 1;
} else {
opacity = (scrollTop - threshold) / fadeLength;
}
}
divFade.css("opacity", opacity);
};
toggleHeader(true);
$(window).scroll(function() {
toggleHeader();
});
});
</script>
The CSS:
*,
*:before,
*:after {
box-sizing: border-box;
}
body {
font-family: 'Open Sans', sans-serif;
}
/*
========================================
Layout: Header
========================================
*/
.header {
width: 100%;
height: 60px;
position: fixed;
top: 0px;
color: #fff;
z-index: 9999;
}
.header-bg {
width: 100%;
height: 60px;
line-height: 60px;
vertical-align: middle;
background: #212121;
position: absolute;
opacity: 0;
font-size: 25px;
}
.logo-top {
background: url(../images/crafthouse-top-logo.png) no-repeat;
width: 171px;
height: 60px;
margin: 0 auto;
}
.menu {
width: 70px;
height: 60px;
padding-top: 20px;
position: absolute;
left: 8%;
}
.menu:hover {
background: #000;
}
.hamburger {
width: 30px;
height: 3px;
background: #fff;
margin: 0 auto;
margin-bottom: 5px;
}
.menu:hover .hamburger {
background: #00ff91;
}
.nav-list {
width: 150px;
margin-top:20px;
background: #000;
display: none;
padding: 20px 0 10px 18px;
text-transform: uppercase;
}
.nav-list li {
margin-bottom: 10px;
}
.nav-list li a {
color: #fff;
text-decoration: none;
font-size: 14px;
}
.nav-list li a:hover {
color: #00ff91;
}
.menu:hover .nav-list {
display: block;
}
.intro {
position: absolute;
right: 0;
bottom: 0;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
background-size: cover;
}
.intro-seperator {
background: url(../images/seperator-brush-top.png);
height: 164px;
width: 100%;
position: absolute;
right: 0;
bottom: 0;
}
.test {
width: 100%;
height: 100%;
background: #fff;
}
/*
========================================
Layout: Content
========================================
*/
.content {
height: 2000px;
}
Use the following for your content:
main{
position:absolute;
top:100%;
}
That moves the actual content below the video (assuming main is your content-element)