DEV Community

Sibtain Jafferi
Sibtain Jafferi

Posted on

Responsive Svelte Components

When creating responsive web applications, my go to strategies are usually css based (flexbox, css grid, media queries).

But what if we want to alter the content of the html based on device? In this case, some javascript must be involved to differentially render the right html.

We can make use of a higher order Svelte component to accomplish this (leveraging named slots).

Component

We'll end up with something like this:

<Responsive>
    <div slot="mobile">...mobile content...</div>
    <div slot="desktop">...desktop content...</div>
</Responsive>
Enter fullscreen mode Exit fullscreen mode

Implementation

// Responsive.svelte

<script>
    import { stores } from "@sapper/app";
    import UAParser from "ua-parser-js";
    // session is passed in server.js
    const { preloading, page, session } = stores();

    const parser = new UAParser();
    parser.setUA($session["user-agent"]);
    const mobile = parser.getResult().device["type"] == "mobile";
</script>

{#if mobile}
    <slot name="mobile" />
{:else}
    <slot name="desktop" />
{/if}
Enter fullscreen mode Exit fullscreen mode

And passing the session in from server.js

import sirv from 'sirv';
import polka from 'polka';
import compression from 'compression';
import * as sapper from '@sapper/server';
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';

polka() // You can also use Express
.use(
    compression({ threshold: 0 }),
    sirv('static', { dev }),
    sapper.middleware({
        session: (req, res) => ({
            'user-agent': req.headers['user-agent']
        })
    })
)
.listen(PORT, err => {
    if (err) console.log('error', err);
});
Enter fullscreen mode Exit fullscreen mode

Now we can differentially load html content with a higher order Svelte component!

Top comments (0)