Hello,
On mobile , the pricing table does not show the arrows to navigate (my mobile uses Chrome browser), although it is well shown on the Mobile View when editing the pricing table on the desktop.
Sure I can use my thumb to navigate, but the arrows are particularly important to show to the user that there is an horizontal scrollbar to use.
I am using the iframe implementation.
Is this a display bug on your side?
3 Likes
Max
February 24, 2025, 2:01pm
3
Hi there, @Dominique_Dubied
Could you please send me a link to the page where your widget is installed?
1 Like
Hi,.
Here is the link
Apprendre la photo avec un cours photo: Débutant - Cours photo privé - Vaud, Fribourg, Vevey, Lausanne, Suisse - Bons cadeaux photo. Vous désirez apprendre la photographie, maîtriser votre appareil photo avec les conseils d'un expert ?
-------- Message d’origine --------
2 Likes
Max
February 24, 2025, 3:03pm
5
Thank you!
I’ve passed this issue on to the devs and will get back to you once I have their response
2 Likes
Max
February 25, 2025, 2:59pm
7
Hi @Dominique_Dubied
Our devs confirmed that the arrows appear for the mobile view only in the configurator, but not on the websites. I am really sorry!
Unfortunately, there is no way to add them now, but we’ll try to consider this opportunity in the future. I’ve added this idea to the Wishlist on your behalf, where we’ll keep you updated - Display navigation arrows on mobile
1 Like
Thanks for your quick reply Max!
Well, I would not consider this as a wishlist, but more as a bug to fix as soon as possible… Indeed the display on the web site is not as the mobile display of the configurator.
Is there a way to fix it quickly ?
3 Likes
Max
February 25, 2025, 3:32pm
9
We haven’t added the arrows for the mobile view, as it’s possible to swipe the table with a finger on mobile.
However, we kept them for the mobile view in the configurator, because you can’t use the swipe option when checking it from the desktop:
We agree that it might cause confusion, and devs are planning to add a hint mentioning that arrows for the mobile view are displayed only in the configurator.
As for the display of the arrows on websites, we’ll try to consider this idea in the future, especially if more users upvote it.
I hope this explains things.
If you have any further questions, I’ll be happy to help
2 Likes
Interesting to note that the Google Reviews plugin IS showing arrows on mobile (and in the configurator).
1 Like
Max
February 26, 2025, 7:03pm
11
Google Reviews widget has a different layout, where a single review is displayed on mobile. In this case, the arrows are necessary to show there are more reviews on the page.
Pricing Table shows one full column and a part of the next column, so the website visitors see that there are more tables on the right and can swipe.
I’ve added the following code to make the navigation work on mobile for the pricing table. Maybe this is useful for others.
Add the id=“elfsight-pricing-table”
<script src="https://static.elfsight.com/platform/platform.js" async></script>
<div id="elfsight-pricing-table" class="YOUR_ID" data-elfsight-app-lazy></div>
Add some javascript and css
<script type='text/javascript'>
// Observe elfsight's div's changes
let observeDOM = (function () {
let MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
return function (obj, callback) {
if (!obj || obj.nodeType !== 1) {
return;
}
if (MutationObserver) {
// define a new observer
let mutationObserver = new MutationObserver(callback);
// have the observer observe for changes in children
mutationObserver.observe(obj, {childList: true, subtree: true});
return mutationObserver;
} else if (window.addEventListener) { // browser support fallback
obj.addEventListener('DOMNodeInserted', callback, false);
obj.addEventListener('DOMNodeRemoved', callback, false);
}
}
})();
// Scroll to element helper
const scrollTo = (el) => {
const elRight = el.offsetLeft + el.offsetWidth;
const elLeft = el.offsetLeft;
const elParentRight = el.parentNode.offsetLeft + el.parentNode.offsetWidth;
const elParentLeft = el.parentNode.offsetLeft;
// Check if right side of the element is not in view
if (elRight > elParentRight + el.parentNode.scrollLeft) {
el.parentNode.scrollLeft = elRight - elParentRight;
}
// Check if left side of the element is not in view
else if (elLeft < elParentLeft + el.parentNode.scrollLeft) {
el.parentNode.scrollLeft = elLeft - elParentLeft;
}
}
class Counter {
constructor() {
this.count = 0;
}
increment() {
this.count = Math.min(this.count + 1, 2)
}
decrease() {
this.count = Math.max(this.count - 1, 0)
}
getCount() {
return this.count;
}
}
const counter = new Counter();
// Observe a specific DOM element:
// This requires adding: id="elfsight-pricing-table" to the <div>
let changed = false;
observeDOM(document.getElementById("elfsight-pricing-table"), function (m) {
if (!changed) {
// Prevent repeating changes
changed = true;
// Helper for the navigation icons
const onNavigate = () => {
switch (counter.getCount()) {
case 0:
// Hide the left arrow
document.getElementById('left-pricing-navigation').style.display = 'none';
// Show the right arrow
document.getElementById('right-pricing-navigation').style.display = 'block';
// Move to element 0
scrollTo(document.getElementsByClassName('es-layout-carousel-snap-carousel')[0].children[0]);
break;
case 1:
// Show the left arrow
document.getElementById('left-pricing-navigation').style.display = 'block';
// Show the right arrow
document.getElementById('right-pricing-navigation').style.display = 'block';
// Move to element 1
scrollTo(document.getElementsByClassName('es-layout-carousel-snap-carousel')[0].children[1]);
break;
case 2:
// Show the left arrow
document.getElementById('left-pricing-navigation').style.display = 'block';
// Hide the right arrow
document.getElementById('right-pricing-navigation').style.display = 'none';
// Move to element 2
scrollTo(document.getElementsByClassName('es-layout-carousel-snap-carousel')[0].children[2]);
break;
}
}
// Debounce to prevent clicking the navigation icons quickly to bug horizontal scrolling
let throttling = false;
const throttle = (closure, timeout = 100) => {
if (throttling) return;
throttling = true
closure();
setTimeout(() => void (throttling = false), timeout);
}
// Add the pointer navigation on mobile
const wrapper = document.getElementsByClassName("snap-carousel__Wrapper-sc-97c6f62c-0")?.[0]
if (wrapper?.childElementCount === 1) {
// Track the original horizontal scroll position
let original = document.getElementsByClassName('es-layout-carousel-snap-carousel')[0].scrollLeft;
// Append the right navigation child (from the copied html)
const rightParent = document.createElement('div');
rightParent.innerHTML = '<div id="right-pricing-navigation" aria-label="Next" role="button" tabindex="0" class="Carousel__CarouselArrowControlContainer-sc-7aac7883-8 snap-carousel__StyledCarouselArrowControlContainer-sc-1c5374ac-0 fMuOTX iBEYbX es-snap-carousel-arrow-control-container"><div class="ArrowControl__ArrowControlContainer-sc-a1566a82-0 ekZpgO es-snap-carousel-arrow-control es-snap-carousel-arrow-control-right" style="width: 32px; height: 32px; background-color: rgba(1, 90, 80, 0.9); fill: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.3) 0px 4px 12px 0px;"><div class="Icon__IconContainer-sc-56cbd5f-0 fkHVdB ArrowControl__ArrowControlIcon-sc-a1566a82-1 koRBCF"><div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M7.04 1.96a1 1 0 0 0-1.497 1.32l.083.094L10.253 8l-4.627 4.626a1 1 0 0 0-.083 1.32l.083.094a1 1 0 0 0 1.32.084l.094-.084 5.334-5.333a1 1 0 0 0 .083-1.32l-.083-.094L7.04 1.96Z"></path></svg></div></div></div></div>'.trim();
const right = rightParent.firstChild;
wrapper.append(right)
// Append the left navigation child (from the copied html)
const leftParent = document.createElement('div');
leftParent.innerHTML = '<div id="left-pricing-navigation" aria-label="Previous" role="button" tabindex="0" class="Carousel__CarouselArrowControlContainer-sc-7aac7883-8 snap-carousel__StyledCarouselArrowControlContainer-sc-1c5374ac-0 fZzkeE boRUuU es-snap-carousel-arrow-control-container"><div class="ArrowControl__ArrowControlContainer-sc-a1566a82-0 ekZpgO es-snap-carousel-arrow-control es-snap-carousel-arrow-control-left" style="width: 32px; height: 32px; background-color: rgba(1, 90, 80, 0.9); fill: rgb(255, 255, 255); box-shadow: rgba(0, 0, 0, 0.3) 0px 4px 12px 0px;"><div class="Icon__IconContainer-sc-56cbd5f-0 fkHVdB ArrowControl__ArrowControlIcon-sc-a1566a82-1 koRBCF"><div><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.96 1.96a1 1 0 0 1 1.497 1.32l-.083.094L5.747 8l4.627 4.626a1 1 0 0 1 .083 1.32l-.083.094a1 1 0 0 1-1.32.084l-.094-.084-5.334-5.333a1 1 0 0 1-.083-1.32l.083-.094L8.96 1.96Z"></path></svg></div></div></div></div>'.trim();
const left = leftParent.firstChild;
wrapper.prepend(left)
// Hide the left by default
left.style.display = 'none';
document.addEventListener('touchstart', () => {
// Store the starting point
original = document.getElementsByClassName('es-layout-carousel-snap-carousel')[0].scrollLeft
})
// Add a horizontal scroll listener for mobile swiping
document.addEventListener('touchend', (event) => {
// To the right, or to the left?
throttle(() => {
switch (true) {
case original < document.getElementsByClassName('es-layout-carousel-snap-carousel')[0].scrollLeft:
// Move right
counter.increment();
onNavigate();
break;
case original > document.getElementsByClassName('es-layout-carousel-snap-carousel')[0].scrollLeft:
// Move left
counter.decrease();
onNavigate();
break;
default:
// Click navigation left
if (event.target.closest('.es-snap-carousel-arrow-control-left')) {
counter.decrease();
onNavigate()
}
// Click navigation right
if (event.target.closest('.es-snap-carousel-arrow-control-right')) {
counter.increment();
onNavigate()
}
break;
}
})
}, false);
}
}
});
</script>
<style>
/* Fix navigation pointers on mobile */
.es-layout-carousel-snap-carousel {
scroll-behavior: smooth !important;
}
.iBgxvD {
scroll-snap-align: initial !important;
}
.iBEYbX {
right: -14px;
}
.boRUuU {
left: -14px;
}
.fMuOTX {
z-index: 2;
flex: 0 1 0;
position: absolute;
top: 50%;
transform: translate(0px, -50%);
right: 0;
}
.fZzkeE {
z-index: 2;
flex: 0 1 0%;
position: absolute;
top: 50%;
transform: translate(0px, -50%);
left: 0px;
}
.fkHVdB {
width: 16px;
height: 16px;
}
.fkHVdB > div {
display: flex;
align-items: center;
justify-content: center;
width: inherit;
height: inherit;
}
.ekZpgO {
position: relative;
display: block;
padding: 0px;
border: medium;
outline: none;
border-radius: 50%;
cursor: pointer;
}
.koRBCF {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.koRBCF svg {
width: 16px !important;
height: 16px !important;
}
</style>
1 Like
Max
March 3, 2025, 6:01pm
13
Hi there, @Katja_Mosina
Many thanks for sharing your tip with us!
I’ve tested your solution with my widget, but, unfortunately, it didn’t work. Could you please send me a link to the page, where your widget is installed, so that we could see it in action?