Skip to content

Flag to let components load global styles  #16563

@kirkas

Description

@kirkas

Feature request

Ability to load 3rd party global styles either conditionally or directly from a component.

Problem description

Forcing the use of .module.css or global.css in app is great when it comes to organizing and practicing healthy css structure, but it starts to be limiting when it comes to 3rd party plugins. (source: https://nextjs.org/docs/basic-features/built-in-css-support#adding-a-global-stylesheet)

Usecase:

I'm trying to implement the great https://github.com/jackocnr/intl-tel-input to make my <input type="tel"/> look nicer. I came up with small re-usable component

import React, {useRef, useEffect} from 'react'
import intlTelInput from 'intl-tel-input'

export default function TelInput(props) {
  const input = useRef(null)
  useEffect(() => {
    intlTelInput(input.current)
  }, [])

  return (
    <input type="tel" ref={input}/>
  )
}

This instantiate the plugin correctly, but the styles are missing. If I import the styles from the components:

// ...
import 'intl-tel-input/build/css/intlTelInput.css'

export default function TelInput(props) {
// ...

I get the (expected) error:

./node_modules/intl-tel-input/build/css/intlTelInput.css
Global CSS cannot be imported from files other than your Custom <App>. Please move all global CSS imports to pages/_app.js. Or convert the import to Component-Level CSS (CSS Modules).
Read more: https://err.sh/next.js/css-global
Location: components/ui/Form/Fields/Tel/Tel.js

As expected, if I add it to my _app.js, it does work.

The issue is that the styles for the plugins will be loaded on each and every page even if TelInput is not present, which essentially breaks the re-usability of my component by making it it dependent on context (App).

Ultimately it's not a big deal to have this one plugin CSS loaded globally, but given the number of plugins out there that require some form of styles import, this could eventually bloat the global style.

Describe the solution you'd like

Potential solutions:

Ideal solution: Scoped flag for import

// Tel.module.sass
.telInput
    @import "intl-tel-input/build/css/intlTelInput" !scoped

Which would render

.telInput__H@Sh .global-declaration { color: red; }

Instead of

.telInput__H@Sh .global-declaration__hAsH { color: red; }

Scope a global import by the given class class:

<style scoped="CustomClass">
.global-declaration { color: red; }
</style>

Renders

<style>
.CustomClass__H@Sh .global-declaration { color: red; }
</style>

Allow global import from node_modules within components, maybe with a flag like

import 'intl-tel-input/build/css/intlTelInput.css' !global

A getStaticStyles implementation which lets you load & compile additional styles for a given page

export async function getStaticStyles() {
  import 'intl-tel-input/build/css/intlTelInput.css'
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions