Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Livewire Window Size Laravel Package

tanthammar/livewire-window-size

Livewire Window Size exposes the browser's window dimensions and responsive breakpoints to your Livewire components, letting you react to resizes and adapt layouts or behavior server-side with minimal JavaScript. Easy to install and use.

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package with Composer, pinning at least 4.0.1:

composer require tanthammar/livewire-window-size:^4.0.1

Version 4.0.1 fixes two defects that made earlier releases effectively unusable for breakpoint logic: the breakpoint list was read from a non-existent livewire-window-size.breakpoints key (so it was always []), and getBreakpoint() declared : array while returning an int (so every call threw a TypeError). Do not start on an older tag; if you inherited one, upgrade before debugging anything else.

This package is only useful in a Livewire + Alpine app. Livewire 3 ships Alpine by default; on Livewire 2 make sure Alpine is loaded before Livewire’s scripts.

Look first at:

  1. The package README for the exact Blade directive and helper names.
  2. The published config file — breakpoints live under breakpoints.window-width (this is the key 4.0.1 corrected).
  3. The package service provider for Blade directives.
  4. mountHasBreakpoints() and getBreakpoint() in the source; they are the two methods that changed.

Confirm the config is actually being read before building anything on top of it:

// tinker
config('breakpoints.window-width'); // expect an array of named breakpoints, not []

Add the package’s window-size tracker once in your main layout, before @livewireScripts:

<livewire:window-size />

Then use it for a low-risk first case, such as swapping navigation:

@windowSize('md')
    <x-desktop-nav />
@else
    <x-mobile-nav />
@endWindowSize

Or use the PHP helper inside a Livewire component’s render() method:

public function render()
{
    return view('livewire.product-list', [
        'columns' => windowSize()->atLeast('lg') ? 4 : 1,
    ]);
}

Verify the behavior in browser responsive mode and watch the Livewire network requests to confirm the server receives the updated size. A quick second check: on 4.0.1, calling getBreakpoint() should return an integer, not throw.

Implementation Patterns

Use one tracker per layout. The tracker should live in your persistent app layout, not inside every page or component. It reports the viewport size to Livewire, which then makes that value available to subsequent server-side renders.

Use Blade directives for coarse branching. They are best for choosing between different component trees, partials, or markup blocks:

@windowSize('lg')
    @livewire('desktop-data-table')
@else
    @livewire('mobile-card-list')
@endWindowSize

Use PHP helpers when data shape changes. If mobile and desktop need different queries, pagination sizes, or relationship loading, branch inside the Livewire component:

public function render()
{
    $perPage = windowSize()->below('md') ? 10 : 50;

    return view('livewire.orders', [
        'orders' => Order::latest()->paginate($perPage),
    ]);
}

Align breakpoints with Tailwind. The package reads breakpoints.window-width; mirror your Tailwind screens config there so sm, md, lg, xl, and 2xl agree. Keep the mapping in one place — a shared config or a documented table — so CSS-driven layout and server-driven content do not disagree.

Assert the breakpoint map is loaded in a test. Since 4.0.1 exists precisely because the config key silently resolved to [], add a cheap guard so a future config rename fails loudly rather than degrading to "no breakpoints ever match":

public function test_window_size_breakpoints_are_configured(): void
{
    $this->assertNotEmpty(config('breakpoints.window-width'));
}

Pair with lazy-loaded Livewire components. This package shines when the mobile and desktop experiences are genuinely different components rather than just different CSS:

@windowSize('md')
    @livewire('desktop-calendar')
@else
    @livewire('mobile-agenda')
@endWindowSize

Design for a default first render. The initial HTTP request does not know the browser width. Render a sensible default, then let the tracker update the Livewire state and re-render. Avoid relying on the correct size being known on the very first paint.

Persist and reuse the reported size. If the package stores the width in session or a cookie, subsequent Livewire requests can branch immediately. If you need this across full page loads, confirm the persistence behavior in the README and add your own cookie if necessary.

Test both branches. In feature tests, set the package’s session/cookie value or bind the helper to simulate mobile and desktop renders:

$this->withSession(['window_size' => 'sm'])
    ->get('/dashboard')
    ->assertSee('Mobile dashboard');

Gotchas and Tips

Upgrade to 4.0.1 before diagnosing "breakpoints don’t work". Two historic failure modes are now fixed and should not be re-investigated: on older versions the breakpoint list was always empty (the config key read was wrong, so every named breakpoint lookup failed), and getBreakpoint() declared : array but returned an int, throwing a TypeError on every call. If you see a TypeError mentioning getBreakpoint, you are on a pre-4.0.1 tag. Pin ^4.0.1 and lock it in CI.

Treat the getBreakpoint(): int signature as public API. If you extended the package, wrapped it, or mocked these methods in tests, update any stub that returns an array or relies on the old key livewire-window-size.breakpoints. Check for both strings when grepping an existing codebase.

The first render problem is unavoidable. The server cannot know window.innerWidth until Alpine reports it. Expect an initial default render followed by a Livewire update. Do not put critical layout or above-the-fold content behind this package unless the default is acceptable.

Do not use it as a CSS replacement. Responsive layout, images, spacing, and typography should stay in CSS. Use this package only when the server must choose different markup, components, queries, or data.

No-JS users and crawlers get the fallback. Alpine and Livewire are required. Search engine bots may not report a viewport size, so avoid branching indexable content on window size. Keep SEO-critical content identical or CSS-responsive.

Watch caching carefully. If you full-page cache views that contain window-size-specific output, a mobile render can be served to desktop users. Either disable page caching for those blocks, vary the cache by a window-size cookie, or keep cached content size-agnostic.

Avoid layout shift and flicker. Because the correct branch may only appear after a Livewire round trip, reserve space or keep the initial default visually close to both variants. Do not use this for large layout regions that would visibly jump.

Keep breakpoints in one place. A common bug is Tailwind saying md is 768px while breakpoints.window-width says something else. Publish and edit the package config, then document that Tailwind and the package share the same breakpoint map.

Do not track on every resize event unnecessarily. If the package debounces resize handling, leave it alone. If you add custom tracking, debounce or only update when crossing a breakpoint to avoid excessive Livewire requests.

Load order matters. Alpine must initialize before the tracker can report sizes. In Livewire 3 this is usually fine; in Livewire 2 confirm Alpine is loaded before Livewire scripts and that the tracker is not inside a nested Alpine scope that prevents initialization.

Debug by inspecting four things. Browser devtools responsive mode; the Livewire component payload in the network tab; the stored window size in session or cookies; and config('breakpoints.window-width') — if that returns [], nothing will ever match regardless of what the browser reports. If the helper always returns the default, the tracker is not reporting, the value is not persisting, or the breakpoint map is empty.

Treat it as a small, niche package. With few stars and dependents, pin the version and test upgrades; 4.0.1 is a good illustration of how much a single config-key and return-type fix can change. Read the source if behavior is unclear; the package surface is small. Prefer CSS and Alpine for purely visual responsiveness, and reach for this package only when the server genuinely needs to know the viewport size.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels