DEV Community

ahmet gedik
ahmet gedik

Posted on

Core Web Vitals Optimization for Video Websites

Video websites are among the hardest to optimize for Core Web Vitals. Heavy thumbnails, dynamic content, and embedded players fight against every performance metric. Here's how I optimized TrendVidStream from a PageSpeed score of 50 to 71-90 on mobile.

The Metrics That Matter

  • LCP (Largest Contentful Paint): < 2.5s target
  • CLS (Cumulative Layout Shift): < 0.1 target
  • INP (Interaction to Next Paint): < 200ms target

LCP Optimization

The hero thumbnail is typically the LCP element on video sites.

<!-- Prioritize the hero image -->
<img src="/thumb/hero.webp"
     alt="Trending video thumbnail"
     width="640" height="360"
     fetchpriority="high"
     decoding="async">

<!-- Lazy-load below-fold thumbnails -->
<img src="/thumb/placeholder.svg"
     data-src="/thumb/video2.webp"
     alt="Video thumbnail"
     width="320" height="180"
     loading="lazy"
     decoding="async">
Enter fullscreen mode Exit fullscreen mode
<?php
// Preload critical hero image in HTTP headers
function addPreloadHeaders(string $heroThumb): void
{
    header("Link: <$heroThumb>; rel=preload; as=image; fetchpriority=high");
}
Enter fullscreen mode Exit fullscreen mode

CLS Prevention

The biggest CLS culprits on video sites:

/* Reserve space for thumbnails */
.video-thumb {
    aspect-ratio: 16/9;
    width: 100%;
    background: #1a1a2e;
}

/* Reserve space for the category bar */
.catbar-wrapper {
    min-height: 48px;
}

/* Prevent font-swap layout shift */
@font-face {
    font-family: 'Inter';
    font-display: swap;
    size-adjust: 100%;
}

/* Reserve space for ads */
.ad-slot {
    min-height: 90px;
}
Enter fullscreen mode Exit fullscreen mode

INP Optimization

// Debounce search input
let searchTimer;
const searchInput = document.getElementById('search');
searchInput.addEventListener('input', (e) => {
    clearTimeout(searchTimer);
    searchTimer = setTimeout(() => {
        performSearch(e.target.value);
    }, 300);
});

// Use requestIdleCallback for non-critical work
function trackView(videoId) {
    if ('requestIdleCallback' in window) {
        requestIdleCallback(() => {
            fetch(`/api/track?v=${videoId}`, { method: 'POST' });
        });
    }
}

// Avoid layout-triggering properties in event handlers
function handleScroll() {
    // Use transform instead of top/left
    requestAnimationFrame(() => {
        header.style.transform = `translateY(${offset}px)`;
    });
}
Enter fullscreen mode Exit fullscreen mode

Server-Side Optimization

<?php

class PageRenderer
{
    public function render(string $template, array $data): string
    {
        // Check page cache first
        $cacheKey = $this->getCacheKey();
        $cached = $this->getPageCache($cacheKey);
        if ($cached !== null) {
            return $cached;
        }

        // Render template
        ob_start();
        extract($data);
        require $template;
        $html = ob_get_clean();

        // Minify inline CSS/JS
        $html = $this->minifyInline($html);

        // Save to page cache
        $this->setPageCache($cacheKey, $html);

        return $html;
    }

    private function minifyInline(string $html): string
    {
        // Remove unnecessary whitespace from inline styles
        return preg_replace('/\s+/', ' ', $html);
    }
}
Enter fullscreen mode Exit fullscreen mode

HTTP Cache Headers

<?php

function setPerformanceHeaders(string $pageType): void
{
    $config = match($pageType) {
        'home'     => ['max-age' => 10800, 'swr' => 7200],
        'category' => ['max-age' => 10800, 'swr' => 7200],
        'watch'    => ['max-age' => 21600, 'swr' => 86400],
        'search'   => ['max-age' => 600,   'swr' => 1800],
        default    => ['max-age' => 3600,  'swr' => 3600],
    };

    header("Cache-Control: public, max-age={$config['max-age']}, stale-while-revalidate={$config['swr']}");
    header('Vary: Accept-Encoding');
}
Enter fullscreen mode Exit fullscreen mode

Results

After optimization, TrendVidStream achieves:

  • Mobile PageSpeed: 71-90
  • Desktop PageSpeed: 86+
  • LCP: 1.5-1.8s
  • CLS: 0.02-0.04
  • INP: 78-95ms

The key is treating performance as a first-class requirement, not an afterthought. For video-heavy sites, every byte and every millisecond matters.

The Thumbnail Optimization Deep Dive

On a video platform, thumbnails are the dominant visual element. Every page shows 10-30 thumbnails, each one a separate network request and decode operation. Optimizing thumbnails delivered the largest single performance improvement.

We request appropriately sized thumbnails from YouTube's API. A thumbnail displayed at 320x180 pixels does not need a 1280x720 source image. Using the correct thumbnail resolution reduced page weight by approximately 60 percent on category pages.

Native lazy loading via the loading="lazy" attribute ensures only above-fold thumbnails load immediately. Below-fold images load as the user scrolls, reducing initial page weight significantly. Combined with aspect-ratio: 16/9 on the container, this eliminates layout shift from loading thumbnails.

For TrendVidStream, these optimizations moved the mobile PageSpeed score from the low 50s to consistently hitting 71-90. The investment in performance pays dividends through improved search rankings, better user experience, and higher engagement. Core Web Vitals optimization is one of the highest-return investments a video platform can make.

Top comments (0)