Running Logos Block Documentation
Overview
The Running Logos block is an animated marquee component designed to showcase logos, brands, partners, or client testimonials in a continuously scrolling horizontal display. It features smooth infinite animation with gradient fade effects and Alpine.js-powered dynamic content duplication.
Purpose and Use Cases
Primary Use Cases
Partner showcases with client logos
Brand galleries displaying portfolio work
Certification displays showing credentials
Sponsor recognition for events or content
Technology stacks highlighting tools used
Design Philosophy
The Running Logos block creates visual interest through motion while maintaining readability and performance. The infinite scroll effect draws attention without being overwhelming, perfect for social proof displays.
Component Structure
HTML Architecture
<div class="wrapper marquee-wrapper">
<section class="block bg-background marquee-block">
<div class="container marquee-container flex flex-col gap-12 py-8">
<h2 class="text-base font-medium text-foreground-secondary text-balance marquee-text">
<!-- Optional descriptive text -->
</h2>
<div x-data class="relative w-full">
<div class="relative w-full mx-auto overflow-hidden max-w-7xl">
<div class="absolute left-0 z-20 w-40 h-full bg-gradient-to-r from-background to-transparent marquee-left-gradient"></div>
<div class="absolute right-0 z-20 w-40 h-full bg-gradient-to-l from-background to-transparent marquee-right-gradient"></div>
<div x-ref="content" class="flex animate-marquee">
<div x-ref="item" class="flex items-center justify-around flex-shrink-0 w-full space-x-2 marquee-inner">
<!-- Logo items -->
</div>
</div>
</div>
</div>
</div>
</section>
</div>
CSS Classes Reference
Container Classes
.marquee-wrapper
Purpose: Outermost container for the marquee section
Tailwind Classes:
wrapper
+ custom classes from block settingsCustomization: Add full-width backgrounds, borders, or section styling
Usage: Section-wide visual modifications
.marquee-block
Purpose: Main semantic container with default background
Tailwind Classes:
block bg-background
Default Styling:
.marquee-block { display: block; background-color: var(--background); }
Customization: Override background colors, add borders or shadows
.marquee-container
Purpose: Content width and layout container
Tailwind Classes:
container flex flex-col gap-12 py-8
Default Styling:
.marquee-container { max-width: responsive; /* container */ display: flex; /* flex */ flex-direction: column; /* flex-col */ gap: 3rem; /* gap-12 */ padding-top: 2rem; /* py-8 */ padding-bottom: 2rem; /* py-8 */ }
Typography Classes
.marquee-text
Purpose: Optional descriptive text above logos
Tailwind Classes:
text-base font-medium text-foreground-secondary text-balance
Default Styling:
.marquee-text { font-size: 1rem; /* text-base */ font-weight: 500; /* font-medium */ color: var(--foreground-secondary); /* text-foreground-secondary */ text-wrap: balance; /* text-balance */ }
Animation Container Classes
Marquee Viewport
Purpose: Defines the visible area with overflow hidden
Tailwind Classes:
relative w-full mx-auto overflow-hidden max-w-7xl
Default Styling:
.marquee-viewport { position: relative; /* relative */ width: 100%; /* w-full */ margin-left: auto; /* mx-auto */ margin-right: auto; /* mx-auto */ overflow: hidden; /* overflow-hidden */ max-width: 80rem; /* max-w-7xl (1280px) */ }
.marquee-left-gradient
Purpose: Left fade-out gradient overlay
Tailwind Classes:
absolute left-0 z-20 w-40 h-full bg-gradient-to-r from-background to-transparent
Default Styling:
.marquee-left-gradient { position: absolute; /* absolute */ left: 0; /* left-0 */ z-index: 20; /* z-20 */ width: 10rem; /* w-40 */ height: 100%; /* h-full */ background: linear-gradient(to right, var(--background), transparent); }
.marquee-right-gradient
Purpose: Right fade-out gradient overlay
Tailwind Classes:
absolute right-0 z-20 w-40 h-full bg-gradient-to-l from-background to-transparent
Default Styling:
.marquee-right-gradient { position: absolute; /* absolute */ right: 0; /* right-0 */ z-index: 20; /* z-20 */ width: 10rem; /* w-40 */ height: 100%; /* h-full */ background: linear-gradient(to left, var(--background), transparent); }
Animation Classes
.animate-marquee
Purpose: Container for the scrolling animation
Tailwind Classes:
flex
Custom Animation:
.animate-marquee { display: flex; animation: marquee 20s linear infinite; } @keyframes marquee { 0% { transform: translateX(0); } 100% { transform: translateX(-100%); } }
.marquee-inner
Purpose: Content container that gets duplicated
Tailwind Classes:
flex items-center justify-around flex-shrink-0 w-full space-x-2
Default Styling:
.marquee-inner { display: flex; /* flex */ align-items: center; /* items-center */ justify-content: space-around; /* justify-around */ flex-shrink: 0; /* flex-shrink-0 */ width: 100%; /* w-full */ } .marquee-inner > * + * { margin-left: 0.5rem; /* space-x-2 */ }
.marquee-item
Purpose: Individual logo styling
Tailwind Classes:
h-12 w-12 object-contain
Default Styling:
.marquee-item { height: 3rem; /* h-12 */ width: 3rem; /* w-12 */ object-fit: contain; /* object-contain */ }
Alpine.js Integration
Initialization Script
x-data
x-init="
$nextTick(() => {
const content = $refs.content;
const item = $refs.item;
const clone = item.cloneNode(true);
content.appendChild(clone);
});
"
Functionality
Content Duplication: Clones logo container for seamless loop
Dynamic Loading: Executes after DOM is ready
Performance: Minimal JavaScript footprint
Accessibility: Maintains semantic structure
Content Fields
Available Fields
text (Text): Optional descriptive text above logos
logos (Assets): Collection of logo images
animation_speed (Number): Custom animation duration (future enhancement)
logo_size (Select): Size options for logos (future enhancement)
Field Configuration
# Blueprint configuration
text:
type: text
instructions: 'Optional descriptive text above the logos'
logos:
type: assets
container: assets
max_files: 20
restrict: images
instructions: 'Logo images to display in the marquee'
Block Settings Integration
Custom Classes
{{ $block->block_settings->block_classes ?? '' }} // Applied to .marquee-wrapper
{{ $block->block_settings->container_classes ?? '' }} // Applied to .marquee-container
Inline Styles
{{ $block->block_settings->block_styles ?? '' }} // Applied to .marquee-block
{{ $block->block_settings->container_styles ?? '' }} // Applied to .marquee-container
Animation Customization
Speed Control
/* Faster animation (10 seconds) */
.animate-marquee {
animation: marquee 10s linear infinite;
}
/* Slower animation (30 seconds) */
.animate-marquee {
animation: marquee 30s linear infinite;
}
Direction Control
/* Reverse direction */
@keyframes marquee-reverse {
0% {
transform: translateX(-100%);
}
100% {
transform: translateX(0);
}
}
.animate-marquee-reverse {
animation: marquee-reverse 20s linear infinite;
}
Pause on Hover
.animate-marquee:hover {
animation-play-state: paused;
}
Responsive Behavior
Logo Size Adjustments
/* Mobile */
.marquee-item {
height: 2rem; /* h-8 */
width: 2rem; /* w-8 */
}
/* Tablet */
@media (min-width: 768px) {
.marquee-item {
height: 2.5rem; /* h-10 */
width: 2.5rem; /* w-10 */
}
}
/* Desktop */
@media (min-width: 1024px) {
.marquee-item {
height: 3rem; /* h-12 */
width: 3rem; /* w-12 */
}
}
Container Width
/* Mobile container */
.marquee-viewport {
max-width: 100%;
}
/* Desktop container */
@media (min-width: 1024px) {
.marquee-viewport {
max-width: 80rem; /* max-w-7xl */
}
}
Performance Considerations
Animation Performance
CSS Transforms: Uses GPU-accelerated transforms
Linear Animation: Consistent frame rate
Cloning: Minimal DOM manipulation
Content Optimization: Compress logo images
Image Optimization
Format: Use WebP or AVIF when possible
Size: Optimize images for display size
Loading: Consider lazy loading for many logos
Caching: Leverage browser caching for logos
Accessibility Considerations
Motion Preferences
@media (prefers-reduced-motion: reduce) {
.animate-marquee {
animation: none;
}
.marquee-inner {
overflow-x: auto;
scroll-behavior: smooth;
}
}
Screen Readers
Alt Text: Provide meaningful alt text for logos
ARIA Labels: Consider aria-label for the marquee
Focus Management: Ensure keyboard navigation works
Advanced Customization
Custom Animation Timing
.animate-marquee {
animation: marquee var(--marquee-duration, 20s) linear infinite;
}
Dynamic Logo Loading
@if($block->logos && count($block->logos) > 0)
@foreach($block->logos as $logo)
<img
src="{{ $logo->url }}"
alt="{{ $logo->alt }}"
class="h-12 w-12 object-contain marquee-item"
loading="lazy"
/>
@endforeach
@endif
Conditional Text Display
@if($block->text)
<h2 class="text-base font-medium text-foreground-secondary text-balance marquee-text">
{!! $block->text !!}
</h2>
@endif