npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@arcmantle/vite-plugin-import-css-sheet

v1.0.12

Published

Small plugin that enables the use of tc39/proposal-import-attributes for css files in vite.

Downloads

1,263

Readme

@arcmantle/vite-plugin-import-css-sheet

A Vite plugin that enables the use of TC39 Import Attributes proposal for CSS files. Import CSS files with with { type: 'css' } syntax and get them as CSSStyleSheet objects, perfect for Web Components and Shadow DOM.

Features

  • 🚀 Import CSS as CSSStyleSheet: Transform CSS imports into constructable stylesheets
  • 🎯 TC39 Standard Syntax: Uses the official with { type: 'css' } syntax
  • Vite Integration: Seamless integration with Vite's build process
  • 🤖 Auto-Import: Automatically inject CSS imports for co-located stylesheets
  • 🗜️ CSS Minification: Built-in CSS minification using Lightning CSS
  • 🔧 Customizable: Support for custom transformers and additional code injection
  • 📦 TypeScript Support: Full TypeScript definitions included
  • 🔍 Development Friendly: Watch mode support for CSS file changes

Installation

npm install @arcmantle/vite-plugin-import-css-sheet
# or
pnpm add @arcmantle/vite-plugin-import-css-sheet
# or
yarn add @arcmantle/vite-plugin-import-css-sheet

Usage

Basic Setup

Add the plugin to your vite.config.ts:

import { defineConfig } from 'vite';
import { importCSSSheet } from '@arcmantle/vite-plugin-import-css-sheet';

export default defineConfig({
  plugins: [
    importCSSSheet()
  ]
});

Import CSS as CSSStyleSheet

Use the TC39 import attributes syntax to import CSS files as CSSStyleSheet objects:

// Import CSS as CSSStyleSheet
import styles from './component.css' with { type: 'css' };

// Use with Web Components
class MyComponent extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });

    // Apply the stylesheet to shadow DOM
    shadow.adoptedStyleSheets = [styles];

    shadow.innerHTML = `
      <div class="container">
        <h1>Hello World</h1>
      </div>
    `;
  }
}

customElements.define('my-component', MyComponent);

Lit Integration

Perfect for Lit components:

import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import componentStyles from './component.css' with { type: 'css' };

@customElement('my-lit-component')
export class MyLitComponent extends LitElement {
  static styles = [componentStyles];

  render() {
    return html`
      <div class="container">
        <p>Styled with imported CSS sheet!</p>
      </div>
    `;
  }
}

TypeScript Support

Include the provided type definitions in your project:

// In your vite-env.d.ts or types file
/// <reference types="@arcmantle/vite-plugin-import-css-sheet/client" />

This provides proper TypeScript support for CSS imports:

// TypeScript will know this is a CSSStyleSheet
import styles from './styles.css' with { type: 'css' };

Configuration

The plugin accepts several configuration options:

import { importCSSSheet } from '@arcmantle/vite-plugin-import-css-sheet';

export default defineConfig({
  plugins: [
    importCSSSheet({
      // Custom CSS transformers
      transformers: [
        (code, id) => {
          // Custom transformation logic
          return code.replace(/\$primary-color/g, '#007bff');
        }
      ],

      // Additional code to inject
      additionalCode: [
        'console.log("CSS sheet loaded:", sheet);'
      ],

      // Disable minification (enabled by default)
      minify: false
    })
  ]
});

Configuration Options

| Option | Type | Default | Description | |--------|------|---------|-------------| | transformers | ((code: string, id: string) => string)[] | [] | Array of functions to transform CSS before converting to stylesheet | | additionalCode | string[] | [] | Additional JavaScript code to inject into the generated module | | minify | boolean | true | Whether to minify CSS using Lightning CSS | | autoImport | object | undefined | Configuration for automatic CSS import injection |

Auto-Import Feature

The auto-import feature automatically detects when a .css file exists alongside your component file and automatically injects the import statement and adds it to your component's static styles property. This is perfect for component-based frameworks like Lit.

How It Works

When you have co-located CSS files:

src/
  ├── my-component.ts
  └── my-component.css

The plugin can automatically transform your component to include the CSS import, eliminating boilerplate.

Auto-Import Configuration

Enable auto-import by providing the autoImport configuration:

import { importCSSSheet } from '@arcmantle/vite-plugin-import-css-sheet';

export default defineConfig({
  plugins: [
    importCSSSheet({
      autoImport: {
        identifier: [
          {
            className: 'LitElement',
            styleName: 'styles',
            position: 'prepend' // or 'append'
          }
        ]
      }
    })
  ]
});

Auto-Import Options

| Property | Type | Required | Description | |----------|------|----------|-------------| | className | string | Yes | The base class name to detect (e.g., 'LitElement', 'HTMLElement') | | styleName | string | Yes | The static property name to inject the stylesheet into (e.g., 'styles') | | position | 'prepend' \| 'append' | No | Where to add the stylesheet in the array. Default: 'prepend' |

Example: Without Auto-Import

// my-component.ts
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
import componentStyles from './my-component.css' with { type: 'css' };

@customElement('my-component')
export class MyComponent extends LitElement {
  static styles = [componentStyles]; // Manually added

  render() {
    return html`<div>Hello World</div>`;
  }
}

Example: With Auto-Import

With auto-import enabled, you can omit the import and static property:

// my-component.ts
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';
// Import is automatically injected!

@customElement('my-component')
export class MyComponent extends LitElement {
  // static styles is automatically created/updated!

  render() {
    return html`<div>Hello World</div>`;
  }
}

The plugin automatically transforms this to:

import my_component_styles from './my-component.css' with { type: 'css' };
import { LitElement, html } from 'lit';
import { customElement } from 'lit/decorators.js';

@customElement('my-component')
export class MyComponent extends LitElement {
  static styles = [my_component_styles]; // Auto-injected!

  render() {
    return html`<div>Hello World</div>`;
  }
}

Auto-Import with Existing Styles

If you already have a static styles property, the auto-import will add to it:

// Before transformation
import { LitElement } from 'lit';
import sharedStyles from './shared.css' with { type: 'css' };

export class MyComponent extends LitElement {
  static styles = [sharedStyles];
}

// After transformation (with position: 'prepend')
import my_component_styles from './my-component.css' with { type: 'css' };
import { LitElement } from 'lit';
import sharedStyles from './shared.css' with { type: 'css' };

export class MyComponent extends LitElement {
  static styles = [my_component_styles, sharedStyles]; // Prepended
}

// After transformation (with position: 'append')
export class MyComponent extends LitElement {
  static styles = [sharedStyles, my_component_styles]; // Appended
}

Multiple Class Support

You can configure auto-import for multiple base classes:

importCSSSheet({
  autoImport: {
    identifier: [
      {
        className: 'LitElement',
        styleName: 'styles',
        position: 'prepend'
      },
      {
        className: 'CustomBaseElement',
        styleName: 'styleSheets',
        position: 'append'
      },
      {
        className: 'MyFrameworkComponent',
        styleName: 'componentStyles'
      }
    ]
  }
})

When Auto-Import Triggers

The auto-import feature only activates when:

  1. A .css file exists with the same name as your component file
  2. Your class extends one of the configured base classes
  3. The file is a supported type (.ts, .tsx, .js, .jsx, .mts, .mjs)

Position: Prepend vs Append

The position option controls CSS cascade order:

  • prepend (default): Component styles come first, can be overridden by later styles
  • append: Component styles come last, override earlier styles
// position: 'prepend'
static styles = [componentStyles, baseStyles, themeStyles];
//                ^^^^^^^^^^^^^^ auto-imported (lowest specificity)

// position: 'append'
static styles = [baseStyles, themeStyles, componentStyles];
//                                        ^^^^^^^^^^^^^^ auto-imported (highest specificity)

Benefits of Auto-Import

Less Boilerplate: No need to manually import and assign stylesheets ✅ Co-location: Encourages keeping styles next to components ✅ Consistency: Automatic naming conventions ✅ Flexibility: Works with existing manual imports ✅ Type-Safe: Full TypeScript support with source maps

Plugin Architecture

  1. Detection: The plugin scans your source files for CSS imports using the with { type: 'css' } syntax
  2. Virtual Modules: Creates virtual modules for CSS files that need to be converted
  3. Transformation: Processes CSS through any custom transformers and minification
  4. Code Generation: Generates JavaScript code that creates a CSSStyleSheet object
  5. Export: Exports the stylesheet as the default export

Browser Support

This plugin generates code that uses the Constructable Stylesheets API:

  • Chrome/Edge 73+
  • Firefox 101+
  • Safari 16.4+

For older browsers, consider using a polyfill.

Why Use This Plugin?

Traditional CSS Imports

// Traditional Vite CSS import (injects into document)
import './styles.css';

With This Plugin

// Get CSS as CSSStyleSheet object
import styles from './styles.css' with { type: 'css' };

// Perfect for Shadow DOM
shadowRoot.adoptedStyleSheets = [styles];

Benefits

  • Encapsulation: Styles don't leak into global scope
  • Performance: No style injection/removal overhead
  • Standards Compliant: Uses official TC39 syntax
  • Shadow DOM Ready: Perfect for Web Components
  • Tree Shakable: Only load styles when needed

Examples

Multiple Stylesheets

import baseStyles from './base.css' with { type: 'css' };
import themeStyles from './theme.css' with { type: 'css' };
import componentStyles from './component.css' with { type: 'css' };

// Combine multiple stylesheets
element.shadowRoot.adoptedStyleSheets = [
  baseStyles,
  themeStyles,
  componentStyles
];

Dynamic Style Loading

// Conditional style loading
const isDark = document.body.classList.contains('dark-theme');
const themeStyles = isDark
  ? await import('./dark-theme.css' with { type: 'css' })
  : await import('./light-theme.css' with { type: 'css' });

shadowRoot.adoptedStyleSheets = [baseStyles, themeStyles.default];

Development

# Install dependencies
pnpm install

# Run demo in development mode
pnpm dev

# Build the plugin
pnpm build

Requirements

  • Node.js >= 22
  • Vite >= 7.0.0

Dependencies

  • lightningcss: Fast CSS transformer and minifier for CSS processing

License

Apache-2.0

Contributing

This package is part of the Arcmantle Weave monorepo. Contributions are welcome! .......