Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regarding limitations of expressions in styles #47

Closed
johanalkstal opened this issue Apr 13, 2019 · 2 comments
Closed

Regarding limitations of expressions in styles #47

johanalkstal opened this issue Apr 13, 2019 · 2 comments

Comments

@johanalkstal
Copy link

johanalkstal commented Apr 13, 2019

Reading the styling documentation - https://github.com/hybridsjs/hybrids/blob/master/docs/template-engine/styling.md - it says that due to how ShadyCSS works, expressions do not work for browsers that do not support Shadow DOM natively.

I think this is a big limitation to adoption of hybrids because css-in-js is growing ever popular.

I gave it a try and as expected it did not work when running Edge.

Then I kept on reading and saw the part about the style helper and wondered if that doesn't solve the problem anyway? Since it takes css as a string, that string does not have to come from an external file.

So I gave this a try,

const fontSize = {
  normal: "1rem",
};

const style = `
    h1 {
      font-size: ${fontSize.normal};
    }
`;

const App = {
  render: () =>
    html`
      <h1>Hello World</h1>
    `.style(style),
};

And to my amazement this works in Edge! The style is properly scoped and the expression properly evaluated.

So styles with expressions can work with ShadyCSS as well!

You could also take advantage of state properties as well to change style based on them.

const fontSize = {
  normal: "1rem",
};

const style = isRed => `
    h1 {
      color: ${isRed ? "red" : "blue"};
      font-size: ${fontSize.normal};
    }
`;

const App = {
  isRed: true,
  render: ({ isRed }) =>
    html`
      <h1>Hello World</h1>
    `.style(style(isRed)),
};

I don't see any immediate downsides to doing this but perhaps you do?

@smalluban
Copy link
Contributor

Styling limitations exist because of older browser support. It is not a library limitation. You can use expressions in <style> element if you target modern browsers. However, then you should use <style> element in your template rather than passing a string value to .style() helper. Why?

Again, because of polyfills, .style() helper changes the signature of the template (under the hood ShadyCSS creates style element and put it into the head of the document with a special prefix, which is added to all elements of the template. I didn't check, but your example might break with more changes). It means that a template with a different style, like in your example (when changing isRed value) creates a new, unique template ID. When engine takes new template ID, it wipes out "old" template and replaces it with the new one.

Even though your example works, it brings a big performance cost. When you change isRed value, your <h1> element will be replaced with new <h1> element.

For CSS in JS like approach, I recommend using inline styles, which are supported by the template engine:

const App = {
  isRed: true,
  render: ({ isRed }) => html`
    <h1 style={{ color: isRed ? "red" : "blue" }}>Hello World</h1>
  `,
};

You can also create "helper" method, for creating your styles:

const fontSize = {
  normal: "1rem",
};

const style = isRed => ({
  fontSize: fontSize.normal,
  color: isRed ? "red" : "blue",
});

const App = {
  isRed: true,
  render: ({ isRed }) => html`
    <h1 style={style(isRed)}>Hello World</h1>
  `,
};

Although, creating dynamic styles at scale might have some performance impact. Creating a static style, and then using classes or other selectors for switching styles will always be faster.

@johanalkstal
Copy link
Author

Thanks for the discussion. I was sure there were things I had not considered and expected as much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants