<div class="header-slideshow elementor" id="<?= $id ?>">
- <?php foreach($images as $image): ?>
- <div class="header-slideshow-image" style="background-image:url(<?= wp_get_attachment_image_url($image['id'], 'full') ?>);"></div>
+ <?php foreach($images as $index => $image): ?>
+ <div class="header-slideshow-image<?= $index === 0 ? ' showing' : '' ?>"
+ style="background-image:url(<?= wp_get_attachment_image_url($image['id'], 'full') ?>);">
+ </div>
<?php endforeach; ?>
- <?php
- /*
- Here we're hijacking Elementor's built in entrance animations for the title text.
- The class "elementor-element" must be present for it to be attached to the waypoints.
- The other classes are also necessary for making the animation work...
- After recent updates, the parent must also have the class "elementor" for animations to work.
- */
- ?>
+ <?php // TODO: Have separate mobile images in portrait crop? Simplest might be to use an inline CSS block with media queries like on SolaireBox? ?>
+
<div class="header-slideshow-sizer" style="padding-bottom: <?= $image_ratio ?>;">
+ <?php
+ /*
+ Here we're hijacking Elementor's built in entrance animations for the title text.
+ The class "elementor-element" must be present for it to be attached to the waypoints.
+ The other classes are also necessary for making the animation work...
+ After recent updates, the parent must also have the class "elementor" for animations to work.
+ */
+ ?>
+
<div class="header-slideshow-content mx-2v elementor-element elementor-invisible" data-settings='{"animation":"fadeInRight","animation_delay":0}' data-element_type="section">
<h1 class="header-slideshow-title">
<span class="header-slideshow-title-text"><?= nl2br($title) ?></span>
// Inspired by: https://www.sitepoint.com/make-a-simple-javascript-slideshow-without-jquery/
const slides = $scope.find('.header-slideshow-image');
- const slideInterval = setInterval(nextSlide, 3000);
+ const slideInterval = setInterval(nextSlide, 4000);
let currentSlide = 0;
+ initSlideshow();
+
+ // Todo: handle resizing here for small screens - scale content (origin: bottom left) so it always fits...
+ // Todo: when scaling, set content div to 100% and title element to display inline-block to keep correct appearance.
+
+
+ function initSlideshow() {
+ let slideshowDots = document.createElement('ul');
+ slideshowDots.className = 'header-slideshow-dots';
+
+ // Build dots navigation
+ slides.each(function (index) {
+ let item = document.createElement('li');
+ item.setAttribute('data-slide', index);
+ if (index === 0) {
+ item.className = 'active';
+ }
+ slideshowDots.appendChild(item);
+ });
+
+ $scope.append(slideshowDots);
+
+ $(document).on('click', '.header-slideshow-dots li', function() {
+ clearInterval(slideInterval); // Stop autoplay
+ showSlide($(this).data('slide'));
+ });
+ }
+
function showSlide(index) {
$(slides[currentSlide]).removeClass('showing');
+ $scope.find(`[data-slide="${currentSlide}"]`).removeClass('active');
currentSlide = (index + slides.length) % slides.length;
$(slides[currentSlide]).addClass('showing');
+ $scope.find(`[data-slide="${currentSlide}"]`).addClass('active');
}
function nextSlide() {
+$breakpoint-slideshow = 1000px
+
header.site
- .header-slideshow-present &
+ .header-slideshow-present &, .home & // Special case for home page and other pages containing this widget
//+above($breakpoint-menu)
- +above(1000px)
+ +above($breakpoint-slideshow)
position: absolute
top: 0
left: 0
position: relative
&-sizer
- @apply bg-cover bg-center
-
- &:before
- content: ''
- position: absolute
- top: 0
- left: 0
- width: 100%
- height: 100%
- background-image: linear-gradient(to bottom, #fff 10%, transparent 50%)
- z-index: 5
+ // White fade for better readability of menu when slideshow is under it
+ +above($breakpoint-slideshow)
+ &:before
+ content: ''
+ position: absolute
+ top: 0
+ left: 0
+ width: 100%
+ height: 100%
+ background-image: linear-gradient(to bottom, #fff 10%, transparent 50%)
+ z-index: 5
+
+ // Todo: this might be replaced by inline styles and separate mobile specific images
+ +below(600px)
+ padding-bottom: 148% !important // Based off mockup: 555px / 375px
&-image
background-repeat: no-repeat
background-size: cover
+ background-position: center
position: absolute
top: 0
left: 0
height: 100%
z-index: 1
opacity: 0
- transition: opacity 0.75s
+ transition: opacity 1s
&.showing
opacity: 1
z-index: 2
+ &-dots
+ position: absolute
+ left: 0
+ bottom: 2em
+ width: 100%
+ display: flex
+ align-items: center
+ justify-content: center
+ z-index: 15
+
+ +below($breakpoint-slideshow)
+ bottom: 1em
+
+ li
+ @apply bg-purple-dark
+ display: block
+ width: 0.8rem
+ height: @width
+ border-radius: 50%
+ margin: 0 0.25em
+ cursor: pointer
+
+ &.active
+ @apply bg-pink
+
+
&-content
z-index: 10
position: absolute
constrain(left, 5vw)
constrain(bottom, 10vw)
- +below(600px)
- position: static
- left: 0
- bottom: 0
+ .elementor-editor-active &, .elementor-editor-preview &
+ visibility: visible // Animation doesn't trigger in the editor for some reason so just show it
+
+ +below($breakpoint-slideshow)
+ bottom: 4em
// Note: for the title to have a semi-transparent background,
// we're limited by the font properties because the inline
position: relative
line-height: 1.27
padding-right: 1rem // To match inline text below
+ margin-left: 0
&:before
top: 0.6em