diff --git a/assets/css/components/marquee.css b/assets/css/components/marquee.css
new file mode 100644
index 000000000..a56649ad7
--- /dev/null
+++ b/assets/css/components/marquee.css
@@ -0,0 +1,102 @@
+/* Marquee — infinite scrolling banner */
+
+.marquee-wrapper {
+ width: 100%;
+ overflow: hidden;
+ position: relative;
+ padding: 1rem 0;
+ mask-image: linear-gradient(
+ to right,
+ transparent 0%,
+ black 10%,
+ black 90%,
+ transparent 100%
+ );
+ -webkit-mask-image: linear-gradient(
+ to right,
+ transparent 0%,
+ black 10%,
+ black 90%,
+ transparent 100%
+ );
+}
+
+.marquee-track {
+ display: flex;
+ width: max-content;
+ animation: marquee-scroll var(--marquee-speed, 40s) linear infinite;
+ animation-direction: var(--marquee-direction, normal);
+ will-change: transform;
+}
+
+.marquee-track[data-pause-on-hover]:hover {
+ animation-play-state: paused;
+}
+
+.marquee-content {
+ display: flex;
+ gap: 1.5rem;
+ padding-right: 1.5rem;
+}
+
+.marquee-item {
+ display: inline-flex;
+ align-items: center;
+ gap: 0.5rem;
+ padding: 0.5rem 1rem;
+ border-radius: 0.375rem;
+ white-space: nowrap;
+ text-decoration: none;
+ cursor: default;
+ transition: all 0.2s ease;
+
+ @apply bg-neutral-100 dark:bg-neutral-800
+ border border-neutral-200 dark:border-neutral-700
+ text-neutral-700 dark:text-neutral-300;
+}
+
+a.marquee-item {
+ cursor: pointer;
+}
+
+.marquee-item:hover {
+ @apply border-primary-500 dark:border-primary-400
+ bg-neutral-50 dark:bg-neutral-700;
+ transform: translateY(-1px);
+}
+
+.marquee-item-icon {
+ width: 24px;
+ height: 24px;
+ object-fit: contain;
+ flex-shrink: 0;
+}
+
+.marquee-item-label {
+ font-size: 0.8125rem;
+ font-weight: 500;
+ line-height: 1;
+}
+
+@keyframes marquee-scroll {
+ 0% {
+ transform: translateX(0);
+ }
+ 100% {
+ transform: translateX(-50%);
+ }
+}
+
+/* Respect reduced motion preference */
+@media (prefers-reduced-motion: reduce) {
+ .marquee-track {
+ animation: none;
+ }
+ .marquee-content[aria-hidden="true"] {
+ display: none;
+ }
+ .marquee-content {
+ flex-wrap: wrap;
+ justify-content: center;
+ }
+}
diff --git a/exampleSite/content/samples/marquee/index.md b/exampleSite/content/samples/marquee/index.md
new file mode 100644
index 000000000..f665b4bf6
--- /dev/null
+++ b/exampleSite/content/samples/marquee/index.md
@@ -0,0 +1,53 @@
+---
+title: "Marquee"
+date: 2026-04-15
+draft: false
+description: "Demonstration of the marquee shortcode"
+summary: "Showcase an infinite scrolling banner of items such as tech stacks, sponsors, or partner logos."
+tags: ["shortcodes", "marquee"]
+---
+
+## Basic Usage
+
+A simple marquee scrolling left at default speed:
+
+{{< marquee >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/go/go-original.svg" >}}Go{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/python/python-original.svg" >}}Python{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/docker/docker-original.svg" >}}Docker{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/linux/linux-original.svg" >}}Linux{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/git/git-original.svg" >}}Git{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/kubernetes/kubernetes-original.svg" >}}Kubernetes{{< /marquee-item >}}
+{{< /marquee >}}
+
+## Custom Speed & Direction
+
+Scrolling right at a slower pace:
+
+{{< marquee speed="60" direction="right" >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/rust/rust-original.svg" >}}Rust{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/typescript/typescript-original.svg" >}}TypeScript{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/react/react-original.svg" >}}React{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/nextjs/nextjs-original.svg" >}}Next.js{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/postgresql/postgresql-original.svg" >}}PostgreSQL{{< /marquee-item >}}
+{{< /marquee >}}
+
+## With Links
+
+Items can link to external pages:
+
+{{< marquee speed="35" >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/github/github-original.svg" href="https://github.com" >}}GitHub{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/gitlab/gitlab-original.svg" href="https://gitlab.com" >}}GitLab{{< /marquee-item >}}
+ {{< marquee-item icon="https://cdn.jsdelivr.net/gh/devicons/devicon/icons/bitbucket/bitbucket-original.svg" href="https://bitbucket.org" >}}Bitbucket{{< /marquee-item >}}
+{{< /marquee >}}
+
+## Text Only (No Icons)
+
+{{< marquee speed="30" label="Partner list" >}}
+ {{< marquee-item >}}Acme Corp{{< /marquee-item >}}
+ {{< marquee-item >}}Globex Inc{{< /marquee-item >}}
+ {{< marquee-item >}}Initech{{< /marquee-item >}}
+ {{< marquee-item >}}Umbrella Corp{{< /marquee-item >}}
+ {{< marquee-item >}}Stark Industries{{< /marquee-item >}}
+{{< /marquee >}}
diff --git a/layouts/partials/vendor.html b/layouts/partials/vendor.html
index 79f03d55c..54094debd 100644
--- a/layouts/partials/vendor.html
+++ b/layouts/partials/vendor.html
@@ -97,6 +97,17 @@
integrity="{{ $twelementsLib.Data.Integrity }}">
{{ end }}
+{{/* marquee */}}
+{{ if .Page.HasShortcode "marquee" }}
+ {{ $marqueeCSS := resources.Get "css/components/marquee.css" }}
+ {{ $marqueeCSS = $marqueeCSS | resources.Fingerprint (.Site.Params.fingerprintAlgorithm | default "sha512") }}
+
+{{ end }}
+
{{/* youtubeLite */}}
{{ if .Page.HasShortcode "youtubeLite" }}
{{ $youtubeLiteCSS := resources.Get "lib/lite-youtube-embed/lite-yt-embed.css" }}
diff --git a/layouts/shortcodes/marquee-item.html b/layouts/shortcodes/marquee-item.html
new file mode 100644
index 000000000..90cfa1bb0
--- /dev/null
+++ b/layouts/shortcodes/marquee-item.html
@@ -0,0 +1,18 @@
+{{ $icon := .Get "icon" }}
+{{ $href := .Get "href" }}
+
+{{ if $href }}
+
+ {{- with $icon -}}
+
+ {{- end -}}
+ {{- .Inner | markdownify -}}
+
+{{ else }}
+
+ {{- with $icon -}}
+
+ {{- end -}}
+ {{- .Inner | markdownify -}}
+
+{{ end }}
diff --git a/layouts/shortcodes/marquee.html b/layouts/shortcodes/marquee.html
new file mode 100644
index 000000000..c850e729b
--- /dev/null
+++ b/layouts/shortcodes/marquee.html
@@ -0,0 +1,22 @@
+{{ $id := delimit (slice "marquee" (partial "functions/uid.html" .) (now.UnixNano)) "-" }}
+{{ $speed := default "40" (.Get "speed") }}
+{{ $direction := default "left" (.Get "direction") }}
+{{ $pauseOnHover := default true (.Get "pauseOnHover") }}
+
+