I have a small slider that switches the preview
image to the main
image. It works fine now
blade.php
<div class="custom-carousel-section"> <div class="custom-container"> <div class="custom-carousel"> @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image) <div class="custom-carousel__title"> @if($loop->first) <span>{{ $article_block_image->title }}</span> @endif </div> @endforeach @endif @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image) <div class="main-image"> @if($loop->first) <img src="{{ $article_block_image->main_image }}" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}"> @endif </div> @endforeach @endif <div class="img-to-select"> @if(!empty($article_block_images)) @foreach($article_block_images as $article_block_image) <div @if($loop->first) class="img-to-select__item selected" @else class="img-to-select__item" @endif> <img src="{{ $article_block_image->preview_image }}" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}" data-main-src="{{ $article_block_image->main_image }}"> </div> @endforeach @endif </div> </div> </div> </div>
js
$('.img-to-select__item').click(function () { $('.img-to-select__item').removeClass('selected'); $(this).addClass('selected'); $('.main-image > img').attr('src', $(this).children('img').data('main-src')); $('.custom-carousel__title > span').html($(this).children('img').attr('data-title')); });
But I still have a picture mobile_image
, and I want the mobile_image
to change instead of main_image
at the maximum size of 576px, for this I use <picture>
I change my code to like this
<div class="main-image"> @if($loop->first) <picture> <source srcset="{{ $article_block_image->mobile_image }}" media="(max-width: 576px)" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}"> <source srcset="{{ $article_block_image->main_image }}" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}"> <img src="{{ $article_block_image->main_image }}" alt="{{ $article_block_image->image_alt }}" title="{{ $article_block_image->image_title }}" data-title="{{ $article_block_image->title }}"> </picture> @endif </div>
But my slider just stops working
The main image eventually changes to mobile, but the slider itself does not switch
In this case, the preview images also echo, but the main image itself does not change
My slider essentially works like this
I just need to put what in the main-image
class in <picture>
and change the image depending on the screen size
Advertisement
Answer
This line is problematic:
$('.main-image > img').attr('src', $(this).children('img').data('main-src'));
The symbol >
means that img
must be an immediate child of .main-image
. So you have to choose one of the selectors $('.main-image img')
or $('.main-image > picture > img')
. But that still won’t work because…
The second problem is that you don’t fully understand how <picture>
works. The browser chooses <source>
to display itself, based on the rules in media
. And the same <img>
is only for browsers, which doesn’t support <picture>
.
So setting .attr('src'
only works if you remove all <source>
.
Also in many places you use .children('img')
.
So if you want to do such substitutions, you have to remove responsive image selection.
I believe the quickest solution for you is to use an alternative syntax. (You will still need to programmatically remove srcset, sizes
)
<img srcset="elva-fairy-480w.jpg 480w, elva-fairy-800w.jpg 800w" sizes="(max-width: 600px) 480px, 800px" src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy">
Another alternative is to swap the entire .main-image
section. eg.:
<div class="main-image"> <picture> <!-- placeholder, insert the correct HTML yourself --> </picture> </div>
And using JS like:
$('.main-image > picture').html(` <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg"> <source media="(min-width: 800px)" srcset="elva-800w.jpg"> <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"> `)
You must store “desktop” and mobile sources in the thumbnail.
<div @if($loop->first) class="img-to-select__item selected" @else class="img-to-select__item" @endif> <img src="{{ $article_block_image->preview_image }}" ... data-main-src="{{ $article_block_image->main_image }}" data-mobile-src="{{ $article_block_image->mobile_image }}" > </div>
The rest is just tedious gluing of strings.
//EDIT: one of possible solutions.
$('.img-to-select__item').click(function () { $('.img-to-select__item').removeClass('selected'); $(this).addClass('selected'); let mainSrc = $(this).children('img').data('main-src') let mobileSrc = $(this).children('img').data('mobile-src') let title = $(this).children('img').attr('title') let alt = $(this).children('img').attr('alt') $('.main-image > picture').html(` <source srcset="{$mobileSrc}" media="(max-width: 576px)" alt="{$alt}" title="{$title}"> <source srcset="{$mainSrc}" alt="{$alt}" title="{$title}"> <img src="{$mainSrc}" alt="{$alt}" title="{$title}"> `); $('.custom-carousel__title > span').html($(this).children('img').attr('data-title')); });
Remember, in JS you work with already generated HTML (provided data), you do not have access to PHP variables.