Created
August 4, 2025 14:24
-
-
Save Jamiewarb/d6d7c701146cd4ab8626f2d136c85719 to your computer and use it in GitHub Desktop.
Example ticker/marquee
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script setup lang="ts"> | |
import { baseTickerVariants } from '.'; | |
export interface TickerProps { | |
repeat?: number; | |
items: string[]; | |
size?: NonNullable<Parameters<typeof baseTickerVariants>[0]>['size']; | |
reversed?: boolean; | |
} | |
const props = withDefaults(defineProps<TickerProps>(), { | |
repeat: 10, | |
size: 'large', | |
reversed: false, | |
}); | |
// Calculates the speed to be 'roughly' the same for all tickers based on the amount of characters | |
const speed = computed(() => { | |
const amountOfCharacters = props.items.reduce((acc, item) => acc + item.length, 0); | |
const amountOfSpaces = props.items.length - 1; | |
const speedPerCharacter = props.size === 'small' ? 200 : 350; | |
return (amountOfCharacters + (amountOfSpaces * 2.5)) * speedPerCharacter; | |
}); | |
</script> | |
<template> | |
<div> | |
<div | |
v-if="size === 'large'" | |
:class="baseTickerVariants({ size, reversed: !reversed, mobile: true })" | |
:style="{ | |
'--c-ticker-animation-duration': `${speed}ms`, | |
}" | |
> | |
<div v-for="index in repeat" :key="index" class="c-ticker__content flex flex-row flex-nowrap items-center"> | |
<div v-for="item of items" :key="item" class="c-ticker__item"> | |
{{ item }} | |
</div> | |
</div> | |
</div> | |
<div | |
:class="baseTickerVariants({ size, reversed })" | |
:style="{ | |
'--c-ticker-animation-duration': `${speed}ms`, | |
}" | |
> | |
<div v-for="index in repeat" :key="index" class="c-ticker__content flex flex-row flex-nowrap items-center"> | |
<div v-for="item of items" :key="item" class="c-ticker__item"> | |
{{ item }} | |
</div> | |
</div> | |
</div> | |
</div> | |
</template> | |
<style scoped> | |
@import '~/assets/css/mixins/_mixins.index.pcss'; | |
.c-ticker { | |
--animation-direction: normal; | |
&--large { | |
--gap: 3.5rem; | |
color: var(--ticker-large-color); | |
@mixin h1; | |
} | |
&--small { | |
--gap: 2.5rem; | |
color: var(--ticker-small-color); | |
@mixin h3; | |
} | |
&--reversed { | |
--animation-direction: reverse; | |
} | |
&--mobile { | |
margin-bottom: 0.5rem; | |
@screen tablet-wide { | |
display: none !important; | |
} | |
} | |
gap: var(--gap); | |
max-width: 100vw; | |
display: flex; | |
overflow: visible; | |
@keyframes ticker { | |
0% { | |
transform: translateX(0); | |
} | |
100% { | |
transform: translateX(calc(-100% - var(--gap))); | |
} | |
} | |
&__content { | |
animation-name: ticker; | |
animation-timing-function: linear; | |
animation-iteration-count: infinite; | |
animation-direction: var(--animation-direction); | |
animation-duration: var(--c-ticker-animation-duration); | |
gap: var(--gap); | |
} | |
&__item { | |
white-space: nowrap; | |
flex-wrap: nowrap; | |
text-transform: uppercase; | |
} | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment