disable left or right arrow at the last item - javascript

Just made a simple div slider with navigation arrows. The div slider works just fine, except, I want some sort of CSS styling to be applied to the arrows.
That is, when a user clicks the left or right arrow, up to the last item, apply CSS styling telling the user they've reached the end of the slider.
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
let container = document.getElementById('slider')
buttonLeft.addEventListener('click', function() {
container.scrollLeft -= 90
})
buttonRight.addEventListener('click', function() {
container.scrollLeft += 90
})
body {
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper {
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider {
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail {
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child) {
margin-right: 10px;
}
div.thumbnail:nth-child(1) {
background-color: darkturquoise;
}
div.thumbnail:nth-child(2) {
background-color: goldenrod;
}
div.thumbnail:nth-child(3) {
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4) {
background-color: powderblue;
}
div.thumbnail:nth-child(5) {
background-color: firebrick;
}
div.thumbnail:nth-child(6) {
background-color: sienna;
}
div.thumbnail:nth-child(7) {
background-color: bisque;
}
div.thumbnail:nth-child(8) {
background-color: navy;
}
div#slide_wrapper>button {
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper>button:hover {
cursor: pointer;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>

Simply check to see if you need to disable each button based on the position of the scroll. Then if there is a need to disable a button, add the disabled class to the button, otherwise remove it.
Future enhancements.
Remove the hardcoded 360 value for the scroll end. This should be calculated from the size of the carousel items and the width of the viewport.
Allow more than one carousel to work with the same code. This could be achieved by using a javascript class that would hold the elements inside an object, separate from other carousels.
See the demo:
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
let container = document.getElementById('slider')
let checkScroll = function() {
if (container.scrollLeft <= 0)
buttonLeft.classList.add("disabled");
else
buttonLeft.classList.remove("disabled");
if (container.scrollLeft >= 360)
buttonRight.classList.add("disabled");
else
buttonRight.classList.remove("disabled");
}
checkScroll();
buttonLeft.addEventListener('click', function() {
container.scrollLeft -= 90;
checkScroll();
})
buttonRight.addEventListener('click', function() {
container.scrollLeft += 90;
checkScroll();
})
body {
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper {
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider {
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail {
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child) {
margin-right: 10px;
}
div.thumbnail:nth-child(1) {
background-color: darkturquoise;
}
div.thumbnail:nth-child(2) {
background-color: goldenrod;
}
div.thumbnail:nth-child(3) {
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4) {
background-color: powderblue;
}
div.thumbnail:nth-child(5) {
background-color: firebrick;
}
div.thumbnail:nth-child(6) {
background-color: sienna;
}
div.thumbnail:nth-child(7) {
background-color: bisque;
}
div.thumbnail:nth-child(8) {
background-color: navy;
}
div#slide_wrapper>button {
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper>button:hover {
cursor: pointer;
}
.slide_arrow.disabled {
opacity: 0.2;
cursor: auto !important;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>

a simple solution to this is to actually create a css class that defines the style of arrows when there are no more items and then just add/remove class based on current index of items

Related

Why does my page width only stretch to 100% with "fit-content"?

I have tried looking around for this but can't seem to find a question to match my current problem. I am trying to build a mock ecommerce website to practice using React. I have a header component. I want this component to be 100% of the screen width, so that the elements inside this component shrink whenever the page shrinks. I have some global css that sets the height and width of the html and body to 100%:
html, body{
background-color: rgb(167, 72, 72);
height: 100%;
min-width: 100%;
}
I am currently facing two problems, neither of which I understand very well the causes of. When I set my header component (the outermost component) to have a width of 100%, the page shrinks correctly. But when I open up developer tools to check the responsiveness, something goes wrong so that the right side of my header is shrinking faster than the page header_shrink
I am able to fix this by setting the width of my header to "fit-content" instead of "100%". Here is what the header looks like when I shrink the page using developer tools.header_fixed But when I do it this way, the components inside of my header don't shrink correctly. For example, my search bar is supposed to decrease in width as I shrink the page, but when I use "fit-content", it just stays set to whatever size it is. search-bar-constant. When I have the width set to 100% instead of fit content, it looks the way it's supposed to search-bar-fixed.
Sorry for the long explanation, but this is the bulk of my problem. "Width: 100%" allows the items in my header component to shrink correctly, but not the component itself. And "width: fit-content" allows the outer header component to shrink correctly, but not the items inside of it.
Here is the JSX I have for reference:
import React from 'react'
import './Header.css'
import { BiSearchAlt2 as SearchIcon} from "react-icons/bi";
import {RiArrowDropDownLine as DropDownIcon} from "react-icons/ri";
import { CgProfile as Profile } from "react-icons/cg";
import { CgShoppingCart as Cart } from "react-icons/cg";
const Header = () => {
const texts = [
'ORDERS OF $5K SHIP FREE',
'FREE SHIPPING ON SELECT ITEMS: SHOP NOW',
'BUY A RIG AND YOUR ENTIRE ORDER SHIPS FREE'
];
let currentTextIndex = 0;
setInterval(() => {
const shippingDealsText = document.querySelector('.shipping-deals-text');
shippingDealsText.classList.add('out');
setTimeout(() => {
shippingDealsText.textContent = texts[currentTextIndex];
shippingDealsText.classList.remove('out');
currentTextIndex = (currentTextIndex + 1) % texts.length;
}, 1000);
}, 5000);
return (
<div className="header">
<div className="header-top">
<div className="top-logo">
<h5 className='small-logo'>LEVIATHAN</h5>
</div>
<div className="space"></div>
<div className="link-container">
<div className="link-wrap">
Gift Cards
</div>
<div className="link-wrap">
Contact Us
</div>
<div className="link-wrap">
Order Status
</div>
<div className="link-wrap">
Live Chat
</div>
</div>
</div>
<div className="header-middle">
<div className="middle-logo">
<h5 className='big-logo'>LEVIATHAN</h5>
</div>
<div className="search-container">
<div className="search-wrapper">
<input
type="text"
id="search-bar"
placeholder="Search"
className='search'
/>
<div className="search-icon-wrapper">
<SearchIcon className='search-icon'/>
</div>
</div>
</div>
<div className="shipping-deals-container">
<div className="button-container">
<div className="shipping-deals-button">
<span className="deals-text">DAILY SHIPPING DEALS </span>
</div>
</div>
<div className="text-container">
<div className="text-slideshow">
<p className="shipping-deals-text">BUY A RIG AND YOUR ENTIRE ORDER SHIPS FREE</p>
</div>
</div>
</div>
<div className="icons-right">
<Profile className='login-pic'/>
<span>Log In</span>
<Cart className='shopping-cart'/>
</div>
</div>
<div className="header-bottom">
<div className="nav-bar">
<ul className='navigation'>
<li className='menu-items'>
<a href="/" className='button drop-down red'>Shop <DropDownIcon className='drop-icon'/></a>
<a href="/" className='button'>Equipment for Crossfit</a>
<a href="/" className='button'>New Gear</a>
<a href="/" className='button'>Barbells</a>
<a href="/" className='button'>Plates</a>
<a href="/" className='button'>Rigs and Racks</a>
<a href="/" className='button'>Shoes</a>
<a href="/" className='button'>Apparel</a>
<a href="/" className='button'>3 Ships Free</a>
<a href="/" className='button'>Zeus</a>
<a href="/" className='button drop-down'>The Index</a>
</li>
</ul>
</div>
</div>
</div>
)
}
export default Header
Here is the styling I am currently applying:
.header {
min-width: 100%;
margin: 0;
padding: 0;
}
.header-top {
background-color: white;
display: flex;
height: 2.5rem;
width: 100%;
}
.top-logo {
position: relative;
margin-left: 3rem;
}
.space {
flex-grow: 1;
}
.small-logo {
padding-top: 0.5em;
position: relative;
font-size: larger;
color: rgb(133, 133, 133)
}
.link-container {
display: flex;
/*border: 1px solid red;*/
margin-right: 3rem;
}
.link-wrap {
/*border: 1px solid green;*/
font-size: 14px;
padding-left: 1rem;
padding-top: 0.75rem;
}
.link-wrap a {
text-decoration: none;
color:#666666;
cursor: pointer;
}
/* Large section of header, black background */
.header-middle {
background-color: black;
height: 7rem;
display: flex;
}
/* Big LEVIATHAN text */
.middle-logo {
/*border: 1px solid red;*/
position: relative;
margin-left: 3rem;
display: flex;
justify-content: center;
align-items: center;
cursor: co;
}
.big-logo {
font-size: 48px;
/*padding-top: 2rem;*/
position: relative;
color: white;
}
.big-logo:hover {
color: rgb(210, 0, 0);
}
.search-container {
position: relative;
width: 40%;
display: flex;
flex-basis: 60%;
margin-left: 3rem;
align-items: center;
justify-content: center;
}
/*This is what has the appearance of the search bar*/
.search-wrapper {
min-width:100%;
height: 35%;
position: relative;
background-color: white;
display: flex;
flex-basis: 50%;
}
.search-icon-wrapper {
display: flex;
justify-content: center;
align-items: center;
width: 3rem;
}
.search-icon {
color: black;
font-size: 20px;
}
/*This is the actual search bar tucked inside*/
.search {
width: 100%;
height: 100%;
border: none;
outline: none;
margin-left: 1em;
font-size: 17px;
}
.search::placeholder {
color:rgb(94, 94, 94);
}
/* This holds onto both our daily shipping deals button */
/* and our text slideshow */
.shipping-deals-container{
width: 18em;
margin-left: 2.5em;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
/*border: 2px solid rgb(136, 77, 255);*/
}
.shipping-deals-button {
width: 65%;
height: 44%;
background-color: rgb(234, 2, 2);
position: relative;
display: flex;
justify-content: center;
align-items: center;
margin-top: 1.5em;
}
.button-container {
width: 100%;
height: 50%;
/*border: 2px solid magenta;*/
}
.deals-text {
color: white;
font-size: 12px;
position: relative;
text-align: center;
align-items: stretch;
width: 100%;
}
.text-container {
/*border: 2px solid rgb(20, 182, 11);*/
width: 100%;
height: 50%;
}
.text-slideshow {
color: white;
width: 100%;
height: 50%;
font-size: 12px;
}
.shipping-deals-text {
transition: opacity 1s;
opacity: 1;
font-size: 13px;
}
.out {
opacity: 0;
transition: opacity 1s;
}
.shipping-deals-text-red{
color: red;
}
.navigation {
display: flex;
align-items:flex-start;
height: 3rem;
}
.menu-items {
height: 100%;
margin-left: 1.5rem;
padding-right: 1.5rem;
display: flex;
align-items: flex-start;
flex: 1;
}
ul {
list-style-type: none;
background-color: #333333;
}
.button {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
text-decoration: none;
color: white;
text-transform: uppercase;
white-space: nowrap;
padding: 1em;
font-weight: bold;
}
.button:hover {
color:rgb(210, 0, 0)
}
.red {
background-color: rgb(210, 0, 0);
}
.red:hover {
color: white;
}
.drop-icon {
font-size: 25px;
}
.icons-right {
height: 50%;
margin-top: 2em;
min-width: 10%;
display: flex;
justify-content: center;
align-items: center;
margin-right: 1rem;
}
.login-pic {
color: white;
font-size: 20px;
}
.shopping-cart {
color: white;
font-size: 20px;
margin-left: 1rem;
}
.icons-right span {
color: white;
margin-left: 0.5em;
}
#media (max-width: 1025px) {
.shipping-deals-container {
display: none;
}
.header-top {
display: none;
}
.header-middle {
height: 50%;
}
.search-wrapper {
border: 2px solid white;
height: 2rem;
}
.icons-right {
margin-bottom: 2rem;
}
}
I have tried altering the width of my body, and html, but nothing seems to be giving me the solution I am looking for
With width: 100% on .header it shrinks the header the way you want it. That seems to be correct actually.
The element that prevents shrinking is <li class="menu-items"></li> because of display: flex;. Flexbox is by default not wrapping (flex-wrap: nowrap;).
Add flex-wrap. wrap; and you'll see everything will shrink with fit-content or width: 100%;
Hope this helps.
On another note: You shouldn't use <li> (List-Element) as the list. Thats what <ul> (Unsorted list) is for.
It should look more like this ->
<ul>
<li>
Shop
</li>
<li>
Equipment for Crossfit
</li>
<li>
New Gear
</li>
<!-- ... -->
</ul>

Make these slides loop?

I have been working on this for a little while, and I think I'm stuck at this point.
I made a div slider with arrows. Each div slide is set to a min-width of 80px.
The code works just fine, except, when I navigate either to the left or the right, it stops at the last item. I want this slider to loop (as in endlessly), instead of ending at the last item.
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
buttonLeft.addEventListener('click', function() {
document.getElementById('slider').scrollLeft -= 90
})
buttonRight.addEventListener('click', function() {
document.getElementById('slider').scrollLeft += 90
})
body{
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper{
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider{
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail{
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child){
margin-right: 10px;
}
div.thumbnail:nth-child(1){
background-color: darkturquoise;
}
div.thumbnail:nth-child(2){
background-color: goldenrod;
}
div.thumbnail:nth-child(3){
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4){
background-color: powderblue;
}
div.thumbnail:nth-child(5){
background-color: firebrick;
}
div.thumbnail:nth-child(6){
background-color: sienna;
}
div.thumbnail:nth-child(7){
background-color: bisque;
}
div.thumbnail:nth-child(8){
background-color: navy;
}
div#slide_wrapper > button{
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper > button:hover{
cursor: pointer;
background-color: dodgerblue;
color: #fff;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>
Nice slider! There are several ways to achieve what you want. In my opinion, the simplest solution would be to work with some if conditions and a counter variable. Once the number of thumbnails is reached, set the counter back to 0.
Update
Regarding to your comment. "How about doing the same for the left arrow.". In the if condition block: if (0 == slideCount) { i add these lines:
slideCount = thumbnail.length // set the slideCounter to maximum
document.getElementById('slider').scrollLeft = slideCount * 90 // calculate the scroll distance
slideCount--; // decrease slidecount
setActive(); // set the red border on the current slide
const buttonLeft = document.getElementById('slide_left')
const buttonRight = document.getElementById('slide_right')
const thumbnail = document.querySelectorAll(".thumbnail");
let slideCount = 0;
setActive();
buttonLeft.addEventListener('click', function() {
if (0 == slideCount) {
slideCount = thumbnail.length
document.getElementById('slider').scrollLeft = slideCount * 90
slideCount--;
setActive();
return;
}
slideCount--;
document.getElementById('slider').scrollLeft -= 90
setActive();
})
buttonRight.addEventListener('click', function() {
slideCount++;
if ( 8 == slideCount) {
document.getElementById('slider').scrollLeft = 0
slideCount = 0;
} else {
document.getElementById('slider').scrollLeft += 90
}
setActive();
})
function setActive() {
thumbnail.forEach(t => {
t.classList.remove("active");
})
thumbnail[slideCount].classList.add("active")
}
function count() {
console.log(slideCount);
}
body{
background-color: #555;
height: 100vh;
display: grid;
align-items: center;
justify-items: center;
font-family: 'Helvetica';
}
div#slide_wrapper{
width: 440px;
display: flex;
justify-content: space-between;
height: fit-content;
}
div#slider{
width: 350px;
display: flex;
height: fit-content;
flex-wrap: nowrap;
overflow: hidden;
}
div.thumbnail{
min-width: 80px;
min-height: 80px;
cursor: pointer;
display: grid;
place-items: center;
font-size: 30px;
}
div.thumbnail:not(:last-child){
margin-right: 10px;
}
div.thumbnail:nth-child(1){
background-color: darkturquoise;
}
div.thumbnail:nth-child(2){
background-color: goldenrod;
}
div.thumbnail:nth-child(3){
background-color: rebeccapurple;
}
div.thumbnail:nth-child(4){
background-color: powderblue;
}
div.thumbnail:nth-child(5){
background-color: firebrick;
}
div.thumbnail:nth-child(6){
background-color: sienna;
}
div.thumbnail:nth-child(7){
background-color: bisque;
}
div.thumbnail:nth-child(8){
background-color: navy;
}
div#slide_wrapper > button{
height: fit-content;
align-self: center;
font-size: 24px;
font-weight: 800;
border: none;
outline: none;
}
div#slide_wrapper > button:hover{
cursor: pointer;
background-color: dodgerblue;
color: #fff;
}
.active {
border: 2px solid red;
}
<div id="slide_wrapper">
<button id="slide_left" class="slide_arrow">❮</button>
<div id="slider">
<div class="thumbnail active">1</div>
<div class="thumbnail">2</div>
<div class="thumbnail">3</div>
<div class="thumbnail">4</div>
<div class="thumbnail">5</div>
<div class="thumbnail">6</div>
<div class="thumbnail">7</div>
<div class="thumbnail">8</div>
</div>
<button id="slide_right" class="slide_arrow">❯</button>
</div>
Just find the width of the slider and compare it with the scroll left like
let buttonLeft = document.getElementById('slide_left')
let buttonRight = document.getElementById('slide_right')
buttonLeft.addEventListener('click', function() {
document.getElementById('slider').scrollLeft -= 90
})
buttonRight.addEventListener('click', function() {
const elem = document.getElementById('slider');
const ElemWidth = elem.getClientRects()[0].width
if(document.getElementById('slider').scrollLeft > ElemWidth ){
document.getElementById('slider').scrollLeft = 0
}else{
document.getElementById('slider').scrollLeft += 90
}
console.log(ElemWidth, document.getElementById('slider').scrollLeft , document.getElementById('slider').scrollLeft > ElemWidth)
})

how to know child divs on container div center on scroll event right and left?

trying to do event 'scroll' and when in the callback function the record of position div only record of last position, i want to know if that div in the center target i want
const slide = document.querySelector(".slides")
slide.addEventListener('scroll', function(e) {
const slide2 = document.querySelector("#slide-2")
console.log(slide2.offsetLeft)
})
<div class="slider">
1
2
3
4
5
<div class="slides">
<div id="slide-1">1</div>
<div id="slide-2">2</div>
<div id="slide-3">3</div>
<div id="slide-4">4</div>
<div id="slide-5">5</div>
</div>
</div>
my goal here I want to know if a user on that div to Right and Left for my slider
so i can make active dots , i am trying to just use native javascript here :)
here is my Codepen example
https://codepen.io/lpllplp222/pen/BaRvwKm
I have used jQuery to achieve the same.
position() function from the jQuery provides the current position of an element from its top and left, I am using the left value to calculate the current active element and get its index, thereby providing an active class to the corresponding dot.
const slide = document.querySelector(".slides")
$('#slider-dots a').on('click', function(event) {
event.stopPropagation();
})
slide.addEventListener('scroll', function(e) {
var scrollLeft = $('#slides-wrapper').scrollLeft();
var currIndex = -1;
$('#slider-dots a').removeClass('active');
for(var i = 0; i<$('#slides-wrapper div').length; i++) {
if($($('#slides-wrapper div')[i]).position().left >= 0 && currIndex === -1) {
currIndex = i;
}
}
$($('#slider-dots a')[currIndex]).addClass('active');
})
* {
box-sizing: border-box;
}
.slider {
width: 400px;
text-align: center;
overflow: hidden;
}
.slides {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
/*
scroll-snap-points-x: repeat(300px);
scroll-snap-type: mandatory;
*/
}
.slides::-webkit-scrollbar {
width: 10px;
height: 10px;
}
#slider-dots a.active {
color: violet;
background-color: #000;
}
.slides::-webkit-scrollbar-thumb {
background: black;
border-radius: 10px;
}
.slides::-webkit-scrollbar-track {
background: transparent;
}
.slides > div {
scroll-snap-align: start;
flex-shrink: 0;
width: 300px;
height: 200px;
margin-right: 50px;
border-radius: 10px;
background: #eee;
transform-origin: center center;
transform: scale(1);
transition: transform 0.5s;
position: relative;
display: flex;
justify-content: center;
align-items: center;
font-size: 100px;
}
.slides > div:target {
/* transform: scale(0.8); */
}
.author-info {
background: rgba(0, 0, 0, 0.75);
color: white;
padding: 0.75rem;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
width: 100%;
margin: 0;
}
.author-info a {
color: white;
}
img {
object-fit: cover;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.slider > a {
display: inline-flex;
width: 1.5rem;
height: 1.5rem;
background: white;
text-decoration: none;
align-items: center;
justify-content: center;
border-radius: 50%;
margin: 0 0 0.5rem 0;
position: relative;
}
.slider > a:active {
top: 1px;
}
.slider > a:focus {
background: #000;
}
/* Don't need button navigation */
#supports (scroll-snap-type) {
.slider > a {
display: none;
}
}
html,
body {
height: 100%;
overflow: hidden;
}
body {
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(to bottom, #74abe2, #5563de);
font-family: "Ropa Sans", sans-serif;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slider" id='slider-dots'>
1
2
3
4
5
<div id='slides-wrapper' class="slides">
<div id="slide-1">
1
</div>
<div id="slide-2">
2
</div>
<div id="slide-3">
3
</div>
<div id="slide-4">
4
</div>
<div id="slide-5">
5
</div>
</div>
</div>

Add and align text to custom Electron Menu bar CSS

So I have the following CSS and HTML for a menu bar:
<header>
<div id="name">Unnamed Masterpiece</div>
<div id="close" onclick="closeWindow()">✕</div>
<div id="min" onclick="minWindow()">―</div>
</header>
header {
display: flex;
justify-content: flex-start;
-webkit-app-region: drag;
background: #292929;
flex-direction: row-reverse;
}
Which, with the close and minimize sign individually styled gives me the following:
However I would like the title to be on the far left and centered.
How would I do this?
Without changing the HTML or CSS you already have, you can add this to you CSS:
#name {
flex: 1;
text-align: center;
order: 1;
}
#close, #min {
order: 0;
}
It will change the order of elements, make the text grow and also center it.
You can try this:
header {
display: flex;
justify-content: flex-start;
-webkit-app-region: drag;
background: #292929;
align-items: center;
}
<header>
<div id="name" style="width: 100%;">Unnamed Masterpiece</div>
<div id="min" onclick="minWindow()" style="">―</div>
<div id="close" onclick="closeWindow()">✕</div>
</header>
Hi You can use like this. I suggest you don't use inline style and by the id style.
<div className="window-header">
<div className="left-side">
Logo - icon
</div>
<div className="draggable-bar" id="titleBar">
Title name or names
</div>
<div className="right-side">
<div id="min-btn" className="btn-box">
<div className="min"></div>
</div>
<div id="max-btn" className="btn-box max">
<div className="maxmize"></div>
</div>
<div id="close-btn" className="btn-box">
<div className="close"></div>
</div>
</div>
</div>
Style codes =>
.window-header {
display: flex;
}
.window-header .left-side, .window-header .draggable-bar, .window-header .right-side {
display: flex;
flex: 1;
}
.window-header .draggable-bar {
-webkit-app-region: drag;
flex-grow: 34;
flex-basis: 0;
align-items: center;
justify-content: center;
color: #c3c3c3;
}
.window-header .draggable-bar:hover {
cursor: move;
}
.window-header .left-side img {
display: flex;
width: 15px;
height: 24px;
margin-top: 3px;
margin-left: 4px;
}
.window-header .left-side .title {
align-items: center;
display: flex;
color: #999;
padding-left: 5px;
user-select: none;
}
.window-header .right-side {
justify-items: flex-end;
justify-content: flex-end;
display: flex;
}
.window-header .right-side .btn-box {
display: inline-flex;
justify-content: center;
width: 30px;
height: 30px;
}
.window-header .right-side .btn-box:hover {
background-color: #797979;
}
.window-header .right-side .btn-box:last-child:hover {
background-color: red;
}
.window-header .right-side .btn-box .min {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNyAyIj48ZGVmcz48c3R5bGU+LmF7ZmlsbDpub25lO3N0cm9rZTojZDNkM2QzO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS13aWR0aDoycHg7fTwvc3R5bGU+PC9kZWZzPjxsaW5lIGNsYXNzPSJhIiB4Mj0iMjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEgMSkiLz48L3N2Zz4=);
width: 15px;
height: 15px;
background-repeat: no-repeat;
position: relative;
top: 50%;
}
.window-header .right-side .btn-box.max .maxmize {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMCAzMCI+PGRlZnM+PHN0eWxlPi5hLC5je2ZpbGw6bm9uZTt9LmF7c3Ryb2tlOiNkM2QzZDM7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO3N0cm9rZS13aWR0aDoycHg7fS5ie3N0cm9rZTpub25lO308L3N0eWxlPjwvZGVmcz48ZyBjbGFzcz0iYSI+PHJlY3QgY2xhc3M9ImIiIHdpZHRoPSIzMCIgaGVpZ2h0PSIzMCIgcng9IjUiLz48cmVjdCBjbGFzcz0iYyIgeD0iMSIgeT0iMSIgd2lkdGg9IjI4IiBoZWlnaHQ9IjI4IiByeD0iNCIvPjwvZz48L3N2Zz4=);
width: 13px;
height: 13px;
background-repeat: no-repeat;
position: relative;
top: 25%;
}
.window-header .right-side .btn-box.unmax .maxmize {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOSA0MyI+PGRlZnM+PHN0eWxlPi5he2ZpbGw6bm9uZTtzdHJva2UtbGluZWNhcDpyb3VuZDt9LmIsLmN7c3Ryb2tlOm5vbmU7fS5je2ZpbGw6I2QzZDNkMzt9PC9zdHlsZT48L2RlZnM+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTMwOCAtMTkyKSI+PGcgY2xhc3M9ImEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMxNyAxOTIpIj48cGF0aCBjbGFzcz0iYiIgZD0iTTUsMEgyNWE1LDUsMCwwLDEsNSw1VjI1YTUsNSwwLDAsMS01LDVIMTlWMTguMzMzYTQuMTA2LDQuMTA2LDAsMCwwLS4yLTEuNTU5LDIuMjUzLDIuMjUzLDAsMCwwLS44NTgtLjk3Nyw0LjQzNyw0LjQzNywwLDAsMC0yLjYzNC0uOEgwVjVBNSw1LDAsMCwxLDUsMFoiLz48cGF0aCBjbGFzcz0iYyIgZD0iTSA1IDIgQyAzLjM0NTc5MDg2MzAzNzEwOSAyIDIgMy4zNDU3OTA4NjMwMzcxMDkgMiA1IEwgMiAxMi45OTg2NTkxMzM5MTExMyBMIDE1LjI5NzA5NTI5ODc2NzA5IDEyLjk5ODY1OTEzMzkxMTEzIEMgMTUuMzA4MDE4Njg0Mzg3MjEgMTIuOTk4NTUwNDE1MDM5MDYgMTUuMzIyMjcwMzkzMzcxNTggMTIuOTk4NDYwNzY5NjUzMzIgMTUuMzM5Njk5NzQ1MTc4MjIgMTIuOTk4NDYwNzY5NjUzMzIgQyAxNS45MDQxNzA5ODk5OTAyMyAxMi45OTg0NjA3Njk2NTMzMiAxNy44MDA2MDE5NTkyMjg1MiAxMy4wODcwNzgwOTQ0ODI0MiAxOS4xNDYzMDEyNjk1MzEyNSAxNC4xOTM2OTEyNTM2NjIxMSBDIDE5LjUyMDg4MTY1MjgzMjAzIDE0LjQ1MDA5NjEzMDM3MTA5IDIwLjI0OTQ0ODc3NjI0NTEyIDE1LjA0NDU4OTk5NjMzNzg5IDIwLjY0OTU1OTAyMDk5NjA5IDE2LjAwNjAzMTAzNjM3Njk1IEMgMjEuMDM0MzEzMjAxOTA0MyAxNi45MzA1NjI5NzMwMjI0NiAyMS4wMjI2MjQ5Njk0ODI0MiAxNy45ODcwMTY2Nzc4NTY0NSAyMSAxOC4zOTU1MzgzMzAwNzgxMyBMIDIxIDI4IEwgMjUgMjggQyAyNi42NTQyMDkxMzY5NjI4OSAyOCAyOCAyNi42NTQyMDkxMzY5NjI4OSAyOCAyNSBMIDI4IDUgQyAyOCAzLjM0NTc5MDg2MzAzNzEwOSAyNi42NTQyMDkxMzY5NjI4OSAyIDI1IDIgTCA1IDIgTSA1IDAgTCAyNSAwIEMgMjcuNzYxNDE5Mjk2MjY0NjUgMCAzMCAyLjIzODU4MDcwMzczNTM1MiAzMCA1IEwgMzAgMjUgQyAzMCAyNy43NjE0MTkyOTYyNjQ2NSAyNy43NjE0MTkyOTYyNjQ2NSAzMCAyNSAzMCBMIDE5IDMwIEwgMTkgMTguMzMzMzMwMTU0NDE4OTUgQyAxOSAxOC4zMzMzMzAxNTQ0MTg5NSAxOS4wNjY4Njk3MzU3MTc3NyAxNy40MDgzNDk5OTA4NDQ3MyAxOC44MDMwNzAwNjgzNTkzOCAxNi43NzQ0NTk4Mzg4NjcxOSBDIDE4LjUzOTI3MDQwMTAwMDk4IDE2LjE0MDU2OTY4Njg4OTY1IDE3Ljk0NDc4OTg4NjQ3NDYxIDE1Ljc5Nzc2MDAwOTc2NTYzIDE3Ljk0NDc4OTg4NjQ3NDYxIDE1Ljc5Nzc2MDAwOTc2NTYzIEMgMTcuMDkzMTE4NjY3NjAyNTQgMTUuMDI3OTQ4Mzc5NTE2NiAxNS41NjgyOTY0MzI0OTUxMiAxNC45OTg0NTY5NTQ5NTYwNSAxNS4zMzk2OTQ5NzY4MDY2NCAxNC45OTg0NTY5NTQ5NTYwNSBDIDE1LjMyMDczMjExNjY5OTIyIDE0Ljk5ODQ1Njk1NDk1NjA1IDE1LjMxMDcwMDQxNjU2NDk0IDE0Ljk5ODY2MDA4NzU4NTQ1IDE1LjMxMDcwMDQxNjU2NDk0IDE0Ljk5ODY2MDA4NzU4NTQ1IEwgMCAxNC45OTg2NjAwODc1ODU0NSBDIDAgMTQuOTk4NjYwMDg3NTg1NDUgMCAxMS40Njc5NTA4MjA5MjI4NSAwIDUgQyAwIDIuMjM4NTgwNzAzNzM1MzUyIDIuMjM4NTgwNzAzNzM1MzUyIDAgNSAwIFoiLz48L2c+PGcgY2xhc3M9ImEiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMwOCAyMDUpIj48cGF0aCBjbGFzcz0iYiIgZD0iTTUsMEgyNWE1LDUsMCwwLDEsNSw1VjI1YTUsNSwwLDAsMS01LDVINWE1LDUsMCwwLDEtNS01VjVBNSw1LDAsMCwxLDUsMFoiLz48cGF0aCBjbGFzcz0iYyIgZD0iTSA1IDIgQyAzLjM0NTc5MDg2MzAzNzEwOSAyIDIgMy4zNDU3OTA4NjMwMzcxMDkgMiA1IEwgMiAyNSBDIDIgMjYuNjU0MjA5MTM2OTYyODkgMy4zNDU3OTA4NjMwMzcxMDkgMjggNSAyOCBMIDI1IDI4IEMgMjYuNjU0MjA5MTM2OTYyODkgMjggMjggMjYuNjU0MjA5MTM2OTYyODkgMjggMjUgTCAyOCA1IEMgMjggMy4zNDU3OTA4NjMwMzcxMDkgMjYuNjU0MjA5MTM2OTYyODkgMiAyNSAyIEwgNSAyIE0gNSAwIEwgMjUgMCBDIDI3Ljc2MTQxOTI5NjI2NDY1IDAgMzAgMi4yMzg1ODA3MDM3MzUzNTIgMzAgNSBMIDMwIDI1IEMgMzAgMjcuNzYxNDE5Mjk2MjY0NjUgMjcuNzYxNDE5Mjk2MjY0NjUgMzAgMjUgMzAgTCA1IDMwIEMgMi4yMzg1ODA3MDM3MzUzNTIgMzAgMCAyNy43NjE0MTkyOTYyNjQ2NSAwIDI1IEwgMCA1IEMgMCAyLjIzODU4MDcwMzczNTM1MiAyLjIzODU4MDcwMzczNTM1MiAwIDUgMCBaIi8+PC9nPjwvZz48L3N2Zz4=);
width: 15px;
height: 15px;
background-repeat: no-repeat;
position: relative;
top: 25%;
}
.window-header .right-side .btn-box .close {
background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMy40MTQgMTMuNDE0Ij48ZGVmcz48c3R5bGU+LmF7ZmlsbDpub25lO3N0cm9rZTojZDNkM2QzO3N0cm9rZS1saW5lY2FwOnJvdW5kO308L3N0eWxlPjwvZGVmcz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjQyLjc5MyAtMTgyLjc5MykiPjxsaW5lIGNsYXNzPSJhIiB4Mj0iMTIiIHkyPSIxMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjQzLjUgMTgzLjUpIi8+PGxpbmUgY2xhc3M9ImEiIHgxPSIxMiIgeTI9IjEyIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyNDMuNSAxODMuNSkiLz48L2c+PC9zdmc+);
width: 12px;
height: 12px;
background-repeat: no-repeat;
position: relative;
position: relative;
top: 30%;
}
This is JS code
function init() {
const window = remote.getCurrentWindow();
document.getElementById("min-btn").addEventListener("click", function (e) {
window.minimize();
});
document.getElementById("max-btn").addEventListener("click", function (e) {
if (!window.isMaximized()) {
this.classList.remove('max')
this.classList.add('unmax')
window.maximize();
} else {
this.classList.remove('unmax')
this.classList.add('max')
window.unmaximize();
}
});
document.getElementById("close-btn").addEventListener("click", function (e) {
window.close();
});
//Listened to the application window sizes and if sizes changed, size icon is changed.
if (remote.getCurrentWindow().isMaximized()) {
document.getElementById("max-btn").classList.remove('max')
document.getElementById("max-btn").classList.add('unmax')
} else {
document.getElementById("max-btn").classList.remove('unmax')
document.getElementById("max-btn").classList.add('max')
}
remote.getCurrentWindow().on('resize', _.debounce(function () {
if (remote.getCurrentWindow().isMaximized()) {
document.getElementById("max-btn").classList.remove('max')
document.getElementById("max-btn").classList.add('unmax')
} else {
document.getElementById("max-btn").classList.remove('unmax')
document.getElementById("max-btn").classList.add('max')
}
}, 100))
};
document.onreadystatechange = function () {
if (document.readyState == "complete") {
init();
}
};

How do I make a button like the JoinVideoCallButton in Discord?

JoinVideoCallButton
Hi!
I simply wonder if anyone here have any idea how to make such a hover effect that could be used for such double option buttons or navbars etc.
I have the css and html code for it but I have no idea how to make the effect work. Also, I wonder if it is possible without the use of Jquery?
body {
background-size: 100%;
margin: 0px;
background-color: gray;
}
.joinVideoCallButton-2Pohj0 {
-ms-flex-align: center;
-ms-flex-pack: center;
-webkit-box-align: center;
-webkit-box-pack: center;
-webkit-box-sizing: border-box;
align-items: center;
background-color: #43b581;
border-radius: 3px;
box-sizing: border-box;
cursor: pointer;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
height: 36px;
justify-content: center;
overflow: hidden;
padding: 0 14px;
position: relative;
}
.joinVideoCallButton-2Pohj0 .underlay-1LCk7B {
-webkit-transition: opacity .1s ease;
background-color: #69c49a;
border-radius: 3px;
bottom: 0;
left: 0;
margin: 2px;
position: absolute;
top: 0;
transition: opacity .1s ease;
width: 50%;
flex: 1 1 auto;
}
.joinVideoCallButton-2Pohj0 .inner-1e8n63 {
cursor: pointer;
z-index: 1;
flex: 1 1 auto;
}
.flex-lFgbSz:first-child, .horizontal-2BEEBe>.flexChild-1KGW5q:first-child {
margin-left: 0;
}
.flex-lFgbSz, .horizontal-2BEEBe>.flexChild-1KGW5q {
margin-left: 10px;
margin-right: 10px;
}
.joinVideoCallButton-2Pohj0 .callDivider-_hMb9n {
background-color: #69c49a;
height: 20px;
margin: 0 2px;
opacity: .6;
width: 2px;
}
.joinVideoCallButton-2Pohj0 .icon-3tOP24 {
height: 16px;
width: 16px;
}
.joinVideoCallButton-2Pohj0 .buttonText-1b8lyZ {
color: #f6f6f7;
font-size: 14px;
margin-left: 8px;
margin-right: 8px;
text-transform: uppercase;
}
.wrapper-1XTKlU{
background-size:cover;
min-height:100vh;
overflow:hidden
}
.flexWrapper-1ztpWj{
height:100vh
}
.flex-3B1Tl4{
display:-webkit-box;
display:-ms-flexbox;
display:flex
}
.alignStart-pnSyE6{
-ms-flex-align:start;
-webkit-box-align:start;
align-items:flex-start
}
.alignEnd-3PVyen{
-ms-flex-align:end;
-webkit-box-align:end;
align-items:flex-end
}
.alignCenter-3VxkQP{
-ms-flex-align:center;
-webkit-box-align:center;
align-items:center
}
.alignStretch-1hwxMa{
-ms-flex-align:stretch;
-webkit-box-align:stretch;
align-items:stretch
}
.alignBaseline-4enZzv{
-ms-flex-align:baseline;
-webkit-box-align:baseline;
align-items:baseline
}
.justifyStart-2yIZo0{
-ms-flex-pack:start;
-webkit-box-pack:start;
justify-content:flex-start
}
.justifyEnd-1ceqOU{
-ms-flex-pack:end;
-webkit-box-pack:end;
justify-content:flex-end
}
.justifyCenter-29N31w{
-ms-flex-pack:center;
-webkit-box-pack:center;
justify-content:center
}
.justifyBetween-1d1Hto{
-ms-flex-pack:justify;
-webkit-box-pack:justify;
justify-content:space-between
}
.horizontal-2VE-Fw>.spacer-2Aeq3k,.horizontalReverse-k5PqxT>.spacer-2Aeq3k,.vertical-3X17r5>.spacer-2Aeq3k{
min-height:1px
}
.horizontal-2BEEBe>.flex-lFgbSz,.horizontal-2BEEBe>.flexChild-1KGW5q{
margin-left:10px;
margin-right:10px
}
.horizontal-2BEEBe>.flex-lFgbSz:first-child,.horizontal-2BEEBe>.flexChild-1KGW5q:first-child{
margin-left:0
}
.horizontal-2BEEBe>.flex-lFgbSz:last-child,.horizontal-2BEEBe>.flexChild-1KGW5q:last-child{
margin-right:0
}
<div class="flex-lFgbSz flex-3B1Tl4 horizontal-2BEEBe horizontal-2VE-Fw flex-3B1Tl4 directionRow-yNbSvJ justifyCenter-29N31w alignStretch-1hwxMa noWrap-v6g9vO private-channel-call-actions" style="">
<div class="joinVideoCallButton-2Pohj0">
<div class="underlay-1LCk7B" style="opacity: 1; transform: translateX(31.5781px);"></div>
<div class="flex-lFgbSz flex-3B1Tl4 horizontal-2BEEBe horizontal-2VE-Fw flex-3B1Tl4 directionRow-yNbSvJ justifyCenter-29N31w alignCenter-3VxkQP noWrap-v6g9vO inner-1e8n63" style="flex: 1 1 auto;">
<div class="flex-lFgbSz flex-3B1Tl4 horizontal-2BEEBe horizontal-2VE-Fw flex-3B1Tl4 directionRow-yNbSvJ justifyCenter-29N31w alignCenter-3VxkQP noWrap-v6g9vO callButton-205P-D" style="flex: 1 1 auto;"><img class="icon-3tOP24" src="http://discordapp.com/assets/0682cf612d4fed39efb57e0a1bcc8544.svg">
<div class="buttonText-1b8lyZ">Video</div>
</div>
<div class="callDivider-_hMb9n"></div>
<div class="flex-lFgbSz flex-3B1Tl4 horizontal-2BEEBe horizontal-2VE-Fw flex-3B1Tl4 directionRow-yNbSvJ justifyCenter-29N31w alignCenter-3VxkQP noWrap-v6g9vO callButton-205P-D" style="flex: 1 1 auto;">
<div class="buttonText-1b8lyZ">Voice</div><img class="icon-3tOP24" src="http://discordapp.com/assets/8b47456a037cc496c55ae8f871274018.svg"></div>
</div>
</div>
</div>
Part 1
The idea is fairly simple: you need to add an extra "hover box" element inside the button row, absolute position it, and finally just change the left value of the object according to the position of the cursor:
function relocateHoverBox(e) {
// Get all the needed values
// (idealy don't use as many variables)
let hoverBoxEl = e.target.closest(".btn-row").querySelector(".btn-row--hover-box");
let hoverBoxHalfWidth = hoverBoxEl.clientWidth / 2;
let containerX = e.target.closest(".btn-row").getBoundingClientRect().left;
let maxLeft = e.target.closest(".btn-row").clientWidth - hoverBoxEl.clientWidth;
let newLeftValue = e.pageX - containerX - hoverBoxHalfWidth;
// Apply new left value accordingly
if (newLeftValue >= 0) {
if (newLeftValue > maxLeft) {
hoverBoxEl.style.left = maxLeft + "px";
}
else {
hoverBoxEl.style.left = e.pageX - containerX - hoverBoxHalfWidth + "px";
}
}
else {
hoverBoxEl.style.left = 0 + "px";
}
}
// Set the hover box in the right position as soon as the mouse enters
const mouseoverHandler = function(e) {
relocateHoverBox(e);
}
// Update the hover box position
const mousemoveHandler = function(e) {
relocateHoverBox(e);
}
// Reset the hover box position
const mouseleaveHandler = function(e) {
e.target.closest(".btn-row").querySelector(".btn-row--hover-box").style.left = "";
}
document.getElementsByClassName("btn-row")[0].addEventListener('mousemove', mousemoveHandler);
document.getElementsByClassName("btn-row")[0].addEventListener('mouseenter', mouseoverHandler);
document.getElementsByClassName("btn-row")[0].addEventListener('mouseleave', mouseleaveHandler);
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: #202225;
}
.btn-row {
display: flex;
justify-content: center;
align-items: center;
border-radius: 4px;
height: 48px;
background: #43b581;
position: relative;
}
.btn-row--hover-box {
width: 50%;
height: 44px;
border-radius: 2px;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.btn-row--hover-box:hover {
background: rgba(255, 255, 255, 0.25);
}
.btn {
background: transparent;
letter-spacing: .1rem;
padding: 0 1rem;
border: 0;
color: #fff;
height: 28px;
display: block;
font-weight: bold;
text-transform: uppercase;
}
<div class="btn-row">
<div class="btn-row--hover-box"></div>
<button class="btn">Option 1</button>
<button class="btn">Option 2</button>
</div>
Part 2
Also, I wonder if it is possible without the use of Jquery?
If by "Jquery" you actually mean the jQuery library, then just remember that it is a library, which means that it is only a collection of useful scripts written in a programming language, then since you can write your own scripts using that language, it is possible to do it without jQuery
If by "Jquery" you mean Javascript (the language in which jQuery is written), then it's not possible to do it without it, since you need it to follow the x-coordinate of the cursor.

Categories

Resources