Skip to main content
pnpm add @winkintel/bootstrap-svelte bootstrap
GitHub

Use Bootstrap 5 with SvelteKit and Svelte 5

Add @winkintel/bootstrap-svelte to a SvelteKit app with Svelte 5, TypeScript/runes APIs, and Bootstrap 5 CSS while leaving Bootstrap JavaScript out of the bundle.


Install Bootstrap Svelte and Bootstrap together. Svelte ^5.29.0 is a peer dependency supplied by your SvelteKit app.

            
            pnpm add @winkintel/bootstrap-svelte bootstrap
        

Bootstrap CSS is required because the components render Bootstrap-compatible classes and markup. Import it once from the root layout or your app stylesheet pipeline.

            
            // src/routes/+layout.ts
import 'bootstrap/dist/css/bootstrap.min.css';

export const prerender = true;
        

If your SvelteKit project already compiles Sass, import Bootstrap SCSS instead.

            
            // src/app.scss
@import 'bootstrap/scss/bootstrap';

// src/routes/+layout.ts
import '../app.scss';
        

The package components are Svelte components that render during SSR and hydrate in the browser. Do not load Bootstrap's JavaScript bundle or individual Bootstrap plugins for the same controls; Bootstrap Svelte owns the component behavior.

  • Keep DOM-only work in Svelte lifecycle code such as onMount.
  • Use component state, for example $state(false), to control modals, collapses, and offcanvas panels.
  • Import Bootstrap CSS once so server-rendered HTML and hydrated HTML use the same class styling.

Use Button for typed Bootstrap button variants, sizes, links, and events.

            
            <script lang="ts">
    import { Button } from '@winkintel/bootstrap-svelte';
</script>

<Button colorVariant="primary" onclick={() => console.log('saved')}>
    Save changes
</Button>
        

Use Navbar with Nav and Container.

            
            <script lang="ts">
    import { Container, Nav, Navbar } from '@winkintel/bootstrap-svelte';
</script>

<Navbar.Root expandOnBreakpoint="lg" class="bg-body-tertiary">
    <Container isFluid={true}>
        <Navbar.Brand href="/">Acme</Navbar.Brand>
        <Navbar.Toggler ariaLabel="Toggle navigation">
            <Navbar.TogglerIcon />
        </Navbar.Toggler>
        <Navbar.Collapse id="mainNavbar">
            <Navbar.Nav class="me-auto mb-2 mb-lg-0">
                <Nav.Item><Nav.Link isActive={true} href="/">Home</Nav.Link></Nav.Item>
                <Nav.Item><Nav.Link href="/settings">Settings</Nav.Link></Nav.Item>
            </Navbar.Nav>
        </Navbar.Collapse>
    </Container>
</Navbar.Root>
        

Use form controls with Svelte bindings and Bootstrap validation classes.

            
            <script lang="ts">
    import { Button, Form } from '@winkintel/bootstrap-svelte';

    let email = $state('');
    let accepted = $state(false);
</script>

<Form.Root method="post" class="needs-validation">
    <div class="mb-3">
        <Form.InputLabel for="email">Email address</Form.InputLabel>
        <Form.EmailInput id="email" name="email" bind:value={email} aria-describedby="email-help" required />
        <Form.HelperText id="email-help">Use a work email address.</Form.HelperText>
    </div>
    <Form.Check class="mb-3">
        <Form.CheckInput id="terms" name="terms" bind:checked={accepted} required />
        <Form.CheckLabel for="terms">I accept the terms</Form.CheckLabel>
    </Form.Check>
    <Button type="submit" colorVariant="primary">Create account</Button>
</Form.Root>
        

Use Modal state instead of Bootstrap JavaScript data attributes.

            
            <script lang="ts">
    import { Button, Modal } from '@winkintel/bootstrap-svelte';

    let isModalShown = $state(false);
</script>

<Button colorVariant="primary" onclick={() => (isModalShown = true)}>
    Open modal
</Button>

<Modal.Root isShown={isModalShown} onHidden={() => (isModalShown = false)}>
    <Modal.Dialog>
        <Modal.Content>
            <Modal.Header isDismissible={true}>
                <Modal.Title level={2} class="fs-5">Confirm action</Modal.Title>
            </Modal.Header>
            <Modal.Body>
                <p>Review the details before continuing.</p>
            </Modal.Body>
            <Modal.Footer>
                <Button colorVariant="secondary" onclick={() => (isModalShown = false)}>Cancel</Button>
                <Button colorVariant="primary">Continue</Button>
            </Modal.Footer>
        </Modal.Content>
    </Modal.Dialog>
</Modal.Root>