我想使用 tailwind 和 owlcarousel 重新创建 Netflix 滑块。它几乎已经按照我想要的方式完成了,但是当我将鼠标悬停在卡片上时,我遇到了一个问题,我对卡片进行了放大以显示详细信息,但实际上我无法单击它们。而且我的物品高度不一样。
有人可以帮我吗?这是小提琴
HTML 结构
<section class="mx-auto w-screen relative flex flex-col gap-4 px-5 mb-16">
<div class="owl-carousel owl-theme">
<div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600 overflow-hidden">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://occ-0-6613-7435.1.nflxso.net/dnm/api/v6/Qs00mKCpRvrkl3HZAN5KwEL1kpE/AAAABQquP3MObc4Xmx8fS1E0EtFypAJFcNs8U73s6OHL2GjPOuIRbKkknfytMjCRkky6eDIe_8LHwBndef1-gQiN3IMX5NEqFRShrIi9MKSOMGvoTalZ2GRya1eswfUOXrTJ6Nnflg.webp?r=bb3"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://placecats.com/340/192" alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://occ-0-6613-7435.1.nflxso.net/dnm/api/v6/Qs00mKCpRvrkl3HZAN5KwEL1kpE/AAAABQquP3MObc4Xmx8fS1E0EtFypAJFcNs8U73s6OHL2GjPOuIRbKkknfytMjCRkky6eDIe_8LHwBndef1-gQiN3IMX5NEqFRShrIi9MKSOMGvoTalZ2GRya1eswfUOXrTJ6Nnflg.webp?r=bb3"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all sm:hover:absolute sm:hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
</div>
</section>
Javascript
const addHoverClasses = (event) => {
const owlitemHovered = event.currentTarget
owlitemHovered.classList.add("!z-10")
owlitemHovered.classList.remove("!z-0")
}
const removeHoverClasses = (event) => {
const owlitemHovered = event.currentTarget
owlitemHovered.classList.remove("!z-10")
owlitemHovered.classList.add("!z-0")
}
const getOwlcarouselResponsiveMaxItems = (event) => {
const owlInstance = event.relatedTarget
const currentBreakpoint = owlInstance._breakpoint
const breakpoints = owlInstance.options.responsive
return breakpoints[currentBreakpoint].items
}
const applyTransformOrigin = (event) => {
const owlCarousel = event.target
const owlItems = owlCarousel.querySelectorAll(".owl-item")
let owlItemActiveCounter = 1
owlItems.forEach((owlItem, index) => {
owlItem.classList.add("!z-0")
owlItem.firstChild.classList.remove(
"origin-[left_center]",
"origin-[right_center]",
"origin-center",
)
if (owlItem?.classList.contains("active")) {
if (owlItemActiveCounter === 1) {
owlItem.firstChild.classList.add("origin-[left_center]")
} else if (
owlItemActiveCounter === getOwlcarouselResponsiveMaxItems(event)
) {
owlItem.firstChild.classList.add("origin-[right_center]")
} else {
owlItem.firstChild.classList.add("origin-center")
}
owlItemActiveCounter++
}
})
}
const applyOwlStyles = (event) => {
const owlCarousel = event.target
const owlItems = owlCarousel.querySelectorAll(".owl-item")
owlCarousel.classList.add("relative")
owlCarousel
.querySelector(".owl-stage-outer")
?.classList.add("!overflow-visible", "!overflow-x-clip")
owlItems.forEach((owlItem, index) => {
owlItem.addEventListener("mouseover", addHoverClasses, false)
owlItem.addEventListener("mouseout", removeHoverClasses, false)
})
const owldotsContainer = owlCarousel.querySelector(".owl-dots")
owldotsContainer?.classList.add(
"absolute",
"!-top-4",
"right-0",
"-translate-y-full",
"!flex",
"!gap-2",
"!items-center",
)
const owldots = owldotsContainer?.querySelectorAll(".owl-dot") ?? []
owldots.forEach((olwDot) => {
const span = olwDot.querySelector("span")
span.classList.add("!m-0", "!rounded-none", "!w-4", "!h-1")
span.classList.remove("!bg-primary-600")
if (olwDot.classList.contains("active")) {
span.classList.add("!bg-primary-600")
}
})
const owlNav = owlCarousel?.querySelector(".owl-nav")
owlNav?.classList.add("!m-0", "!top-0", "!bottom-0", "!w-full")
const owlPrev = owlNav?.querySelector(".owl-prev")
const owlNext = owlNav?.querySelector(".owl-next")
owlPrev?.classList.add(
"!absolute",
"!h-full",
"!m-0",
"!bg-black",
"!bg-opacity-60",
"!text-white",
"!text-6xl",
"!font-opensans",
"!left-0",
"!w-[40px]",
"!rounded-none",
"!rounded-r-md",
"-translate-y-full",
)
owlNext?.classList.add(
"!absolute",
"!h-full",
"!m-0",
"!bg-black",
"!bg-opacity-60",
"!text-white",
"!text-6xl",
"!font-opensans",
"!right-0",
"!w-[40px]",
"!rounded-none",
"!rounded-l-md",
"-translate-y-full",
)
owlPrev?.querySelector("span").classList.add("align-super")
owlNext?.querySelector("span").classList.add("align-super")
}
jQuery(".owl-carousel").owlCarousel({
loop: true,
margin: 10,
stagePadding: 50,
nav: true,
responsive: {
0: {
items: 1,
},
600: {
items: 3,
},
1000: {
items: 5,
},
},
onInitialized: (event) => {
applyOwlStyles(event)
applyTransformOrigin(event)
},
onTranslated: (event) => {
applyTransformOrigin(event)
},
onResized: (event) => {
applyOwlStyles(event)
applyTransformOrigin(event)
},
})
问题在于
.owl-stage:after
的大小为 .owl-item
。
当您使用
scale
时,JavaScript 识别的大小不会改变,并且当您离开实际的轮播而不是缩放后的项目时,会触发 mouseout
上的 .owl-carousel
事件。
为了解决这个问题,我创建了一个名为
.owl-carousel-container
的父 div,它检测轮播的大小并保持相同的大小。在这个 div 中,我允许 .owl-stage:after
达到它想要的大小(9999px)。 这可以防止不良的 mouseout
行为。
为了确保
.owl-carousel-container
div 的大小保持同步,我使用 Owl Carousel 事件并重复使用 setTimeout
来处理可能导致问题的任何延迟。
我添加了多次重复,但你可以测试一下是否可以减少数量。
最后,我还必须同步
.owl-prev
和 .owl-next
按钮的大小。为此,我创建了一个全局变量以确保它们全部一起更新。
const originalWarn = console.warn;
console.warn = (msg, ...args) => {
if (!msg.includes('Tailwind')) {
originalWarn(msg, ...args);
}
};
const htmlElement = document.documentElement,
head = document.querySelector("head")
const scriptTailwind = document.createElement("script")
scriptTailwind.src = "https://cdn.tailwindcss.com/"
head.append(scriptTailwind)
const addHoverClasses = (event) => {
const owlitemHovered = event.currentTarget
owlitemHovered.classList.add("!z-10")
owlitemHovered.classList.remove("!z-0")
}
const removeHoverClasses = (event) => {
const owlitemHovered = event.currentTarget
owlitemHovered.classList.remove("!z-10")
owlitemHovered.classList.add("!z-0")
}
const getOwlcarouselResponsiveMaxItems = (event) => {
const owlInstance = event.relatedTarget
const currentBreakpoint = owlInstance._breakpoint
const breakpoints = owlInstance.options.responsive
return breakpoints[currentBreakpoint].items
}
const applyTransformOrigin = (event) => {
const owlCarousel = event.target
const owlItems = owlCarousel.querySelectorAll(".owl-item")
let owlItemActiveCounter = 1
owlItems.forEach((owlItem, index) => {
owlItem.classList.add("!z-0")
owlItem.firstChild.classList.remove(
"origin-[left_center]",
"origin-[right_center]",
"origin-center",
)
if (owlItem?.classList.contains("active")) {
if (owlItemActiveCounter === 1) {
owlItem.firstChild.classList.add("origin-[left_center]")
} else if (
owlItemActiveCounter === getOwlcarouselResponsiveMaxItems(event)
) {
owlItem.firstChild.classList.add("origin-[right_center]")
} else {
owlItem.firstChild.classList.add("origin-center")
}
owlItemActiveCounter++
}
})
}
const applyOwlStyles = (event) => {
const owlCarousel = event.target
const owlItems = owlCarousel.querySelectorAll(".owl-item")
owlCarousel.classList.add("relative")
owlCarousel
.querySelector(".owl-stage-outer")
?.classList.add("!overflow-visible", "!overflow-x-clip")
owlItems.forEach((owlItem, index) => {
owlItem.addEventListener("mouseover", addHoverClasses, false)
owlItem.addEventListener("mouseout", removeHoverClasses, false)
})
const owldotsContainer = owlCarousel.querySelector(".owl-dots")
owldotsContainer?.classList.add(
"absolute",
"!-top-4",
"right-0",
"-translate-y-full",
"!flex",
"!gap-2",
"!items-center",
)
const owldots = owldotsContainer?.querySelectorAll(".owl-dot") ?? []
owldots.forEach((olwDot) => {
const span = olwDot.querySelector("span")
span.classList.add("!m-0", "!rounded-none", "!w-4", "!h-1")
span.classList.remove("!bg-primary-600")
if (olwDot.classList.contains("active")) {
span.classList.add("!bg-primary-600")
}
})
const owlNav = owlCarousel?.querySelector(".owl-nav")
owlNav?.classList.add("!m-0", "!top-0", "!bottom-0", "!w-full")
const owlPrev = owlNav?.querySelector(".owl-prev")
const owlNext = owlNav?.querySelector(".owl-next")
owlPrev?.classList.add(
"!absolute",
"!h-full",
"!m-0",
"!bg-black",
"!bg-opacity-60",
"!text-white",
"!text-6xl",
"!font-opensans",
"!left-0",
"!w-[40px]",
"!rounded-none",
"!rounded-r-md",
"-translate-y-full",
)
owlNext?.classList.add(
"!absolute",
"!h-full",
"!m-0",
"!bg-black",
"!bg-opacity-60",
"!text-white",
"!text-6xl",
"!font-opensans",
"!right-0",
"!w-[40px]",
"!rounded-none",
"!rounded-l-md",
"-translate-y-full",
)
owlPrev?.querySelector("span").classList.add("align-super")
owlNext?.querySelector("span").classList.add("align-super")
}
jQuery(".owl-carousel").owlCarousel({
loop: true,
margin: 10,
stagePadding: 50,
nav: true,
responsive: {
0: {
items: 1,
},
600: {
items: 3,
},
1000: {
items: 5,
},
},
onInitialized: (event) => {
applyOwlStyles(event)
applyTransformOrigin(event)
resizeContainer(event)
},
onTranslated: (event) => {
applyTransformOrigin(event)
},
onResized: (event) => {
applyOwlStyles(event)
applyTransformOrigin(event)
resizeContainer(event)
},
})
function resizeContainer(event) {
const owlCarousel = event.target
repeat5x(() => {
const height = owlCarousel.querySelector(".owl-item").clientHeight
if (height > 10) {
htmlElement.style.setProperty("--owl-carousel-height", `${height}px`)
}
})
}
function repeat5x(fn) {
setTimeout(fn, 0)
setTimeout(fn, 100)
setTimeout(fn, 333)
setTimeout(fn, 666)
setTimeout(fn, 2500)
}
.owl-carousel-container {
height: var(--owl-carousel-height) !important;
max-height: var(--owl-carousel-height) !important;
}
.owl-prev, .owl-next {
height: var(--owl-carousel-height) !important;
max-height: var(--owl-carousel-height) !important;
top: var(--owl-carousel-height) !important;
}
.owl-carousel {
position: absolute;
top: 0;
left: 0;
height: 9999px;
}
.owl-stage:after {
height: 9999px !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/assets/owl.carousel.min.css" rel="stylesheet"/>
<link href="https://owlcarousel2.github.io/OwlCarousel2/assets/owlcarousel/assets/owl.theme.default.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/OwlCarousel2/2.3.4/owl.carousel.min.js"></script>
<p>another element</p>
<p>another element</p>
<p>another element</p>
<section class="mx-auto w-screen relative flex flex-col gap-4 px-5 mb-20">
<div class="owl-carousel-container">
<div class="owl-carousel owl-theme">
<div class="item group transition-all hover:absolute hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all hover:absolute hover:scale-125 border border-red-600 overflow-hidden">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://occ-0-6613-7435.1.nflxso.net/dnm/api/v6/Qs00mKCpRvrkl3HZAN5KwEL1kpE/AAAABQquP3MObc4Xmx8fS1E0EtFypAJFcNs8U73s6OHL2GjPOuIRbKkknfytMjCRkky6eDIe_8LHwBndef1-gQiN3IMX5NEqFRShrIi9MKSOMGvoTalZ2GRya1eswfUOXrTJ6Nnflg.webp?r=bb3"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all hover:absolute hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all hover:absolute hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://placecats.com/340/192" alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all hover:absolute hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all hover:absolute hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://occ-0-6613-7435.1.nflxso.net/dnm/api/v6/Qs00mKCpRvrkl3HZAN5KwEL1kpE/AAAABQquP3MObc4Xmx8fS1E0EtFypAJFcNs8U73s6OHL2GjPOuIRbKkknfytMjCRkky6eDIe_8LHwBndef1-gQiN3IMX5NEqFRShrIi9MKSOMGvoTalZ2GRya1eswfUOXrTJ6Nnflg.webp?r=bb3"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
<div class="item group transition-all hover:absolute hover:scale-125 border border-red-600">
<div href="#" class="card bg-neutral-900 rounded-md cursor-pointer overflow-hidden">
<div>
<img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQKSRTtOrtjLaagEC2gTK6VsPq4NEFk_72hhg&s"
alt="">
</div>
<div class="hidden group-hover:flex bg-white p-1.5 flex-col h-fit w-full">
<div class="flex gap-3 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
<span class="">
MOVIE TITLE
</span>
</div>
<a href="" class="text-red-600 sm:group-hover:scale-[.8] origin-top-left w-[calc(100%/0.8)]">
try to click me you can't
</a>
</div>
</div>
</div>
</div>
</div>
</section>
<p>another element</p>
<p>another element</p>
<p>another element</p>