atlassian-labs/compiled

Global styles component

itsdouges opened this issue ยท 5 comments

API

We will standardize on the @emotion/react API:

import { Global } from '@compiled/react';

<Global 
  styles={{
    h1: { fontSize: 30 }
  }}
/>

Assumptions

  • Dynamic declarations can't work with global styles
  • Global styles will be extracted to an external stylesheet

Outstanding questions

  • Do we force @font-face declarations to go through this component? Currently they can't be defined anywhere because it will blow up in prod mode
  • How can we conditionally set global styles when they have been extracted to an external stylesheet? If there is no good story for this we may need to just not support this when baked as well.

Is there already a way to add global CSS? Or can you recommend a workaround?

Hi @mhauens there isn't a good work around at the time unfortunately. We will be looking to implement this component in the next round of development (along side the ClassNames component, and keyframes api).

If you needed something like global styles you could wrap your app in an div and then set style to that element for children to inherit. But it's not great.

@mhauens or anyone else interested - another alternative for global-ish styles atm (won't work for SSR, unless you implement something yourself)

import { styled } from '@compiled/react';
import BodyClassName from 'react-body-classname';

export const DisableScroll = styled(BodyClassName)`
  overflow: hidden;
`;

When mounted will add class names to body. When unmounted will remove.

I worked on a spike here for the global component #462 a while back. There are a few things that make it difficult because we want to be able to extract everything to an external style sheet.

If we want to be able to extract all CSS, how can we fundamentally support conditional global CSS? Aka, mount a component, styles are applied, unmount a component, styles are removed.

The solution is obvious if its purely a runtime one. It is complicated by extracting. Even more so that we want to support a runtime to extracted story over the lifecycle of compiled components. Fundamentally the answer could simply be - don't have conditional global styles! Without thinking on names:

  • PermanentGlobalStyles component - for adding "always on" global styles
  • BrowserBodyStyles component - for adding styles that can be "conditional" that only works on the browser, which adds it to the body element

But the downside is PermanentGlobalStyles goes against regular idiomatic React concepts. You could "unmount" the component and the styles wouldn't be removed. And it's even more problematic when you consider third party packages from NPM could set their own global styles, and they aren't ever removed! Oh no.

One thing we could have in our tool belt is the conditionally render style link elements, perhaps? https://developer.mozilla.org/en-US/docs/Web/HTML/Element/link disabled attribute. However seemingly deprecated/not used now, so let's not.

What if we used media attributes instead? Or re-write the CSS to only apply given certain media queries or selectors. We'd want something that doesn't affect specificity though.

The downside would be after extracting we'd need applications to have a provider or something to render these links when appropriate, as well as support SSR story. Realistically we'd need that anyway for critical CSS.

Assuming we can still support the conditional CSS once extracted, we'd probably aim to have two style sheets:

  1. atomic styles
  2. global styles

This is something that Compiled won't currently be supporting. Closing to clean up the issue list.