openstyles / stylus

Stylus - Userstyles Manager
https://add0n.com/stylus.html
GNU General Public License v3.0
5.5k stars 306 forks source link

Feature request: Option syntax for .user.css files which keeps CSS valid and future-proof #314

Closed Athari closed 4 years ago

Athari commented 6 years ago

Intro

I love the new syntax for .user.css files which was introduced in #134 (Install styles from *.user.css file). It solves two major problems with styles on userstyles.org:

  1. Style files are self-contained, so you no longer need to rely on a third-party website to work (especially important considering userstyles.org went straight downhill).
  2. Styles can be installed by accessing a link on any website (again, no relience on a third-party website).

However, it suffers from a serious problem: just like option syntax from userstyles.org, it forces developers to write files which rely on preprocessors, while pure CSS is often sufficient and doesn't require any specific software.

Feature request: \@if

While @var introduces CSS variables, its current functionality is lacking as it only allows using variable values in property values (and calculating new values using calc). The if statement is completely missing, but it's crucial for customizable themes.

I propose adding a new pure CSS syntax for if: @-styl-if (nav-pos == 'bottom'). Reasons:

  1. It's valid CSS. CSS parsers will warn about it, but won't consider an error.
  2. It's clearly marked as a proprietery CSS extension by using the -styl- prefix.

As a result, any conforming CSS parser from the past, present or future, will correctly skip this as an unrecognized at-rule, while parsers supporting it will provide new functionality β€” this is what at-rules are designed for.

Question: Pure CSS \@var

The original proposal suggests that CSS variables are introduced, but all later examples rely on Stylus preprocessor. Without relying on any preprocessors, I could write the following:

/* [...] @var text option-my-width 'My width' 1337px [...] */
:root {
  --my-width: var(--option-my-width, 1337px);
}
body {
  width: var(--my-width);
}

This way, CSS file works correctly both as a stanalone file and with GUI support. I don't like value duplication, but can live with it I guess, given the benefits. Is that the correct appoach?

Question: Workflow

While I'v been using user styles for ages and have written more than a hundred of them, I'm still new to sharing them and try to find a sensible workflow. So far, I've been using Stylish for editing styles and to see changes while I edit the file, then copy-paste the whole text to userstyles.org. I try to find a sensible way to add options to the styles which doesn't ruin the workflow and turn it into an error-prone mess, but I don't see any.

Ideally, I'd like to write pure CSS, with support for options in all user style extensions, as well as easily update online versions. And advice?

(Currently stuck on Firefox 56.)

narcolepticinsomniac commented 6 years ago

I can't find its documentation anywhere other than in the comments to the closed merge request

There's a wiki link in the manager. I'm sure one of the usercss gurus here will respond, but in the meantime, I figured I'd point you in the right direction.

Athari commented 6 years ago

@narcolepticinsomniac Hahaha, I was confused by the lack of numbers on the wiki tab header β€” thought it's empty. πŸ˜†

OK, read the docs. Now it makes sense. Updated the original post and adjusted the feature request.

Mottie commented 6 years ago

it forces developers to write files which rely on preprocessors

You have leave out the @preprocessor meta option and the usercss will still replace userstyles.org style placeholders - e.g. https://gist.github.com/Mottie/82de0c2956b31d9a34c2e49ffbd4d444#file-github-selected-tab-color-uso-user-css

On that same page is another example of the same style using the stylus preprocessor - https://gist.github.com/Mottie/82de0c2956b31d9a34c2e49ffbd4d444#file-github-selected-tab-color-user-css

If you need an if statement, then yes, you'll need to set the @preprocessor stylus setting. Check out these examples:

DanaMW commented 6 years ago

Thanks for the Point-out. I was looking for just that, more complete, working examples. Helped a lot, thank you.

DanaMW commented 6 years ago

While I have someone on the phone... is there a location for editing and saving the default userscript header added to new files? I thought I read there was, looked but haven't found it or info yet. Thanks.

Mottie commented 6 years ago

Create a basic template, then leave the @name empty (see https://github.com/openstyles/stylus/commit/a58f42dee00ad3c7d0e3cd38b6a8e4c3e82522e3).

DanaMW commented 6 years ago

Thank you. Looking now.

Mottie commented 6 years ago

Hmm, it doesn't seem to be working anymore.

Athari commented 6 years ago

@Mottie If I understand correctly, I have to choose between:

  1. no preprocessor: valid CSS, CSS variables, no conditional blocks;
  2. USO preprocessor: invalid CSS, comment variables insert text blocks at any place, conditions by placing code in comments;
  3. Stylus preprocessor: invalid CSS, unprefixed stylus variables, conditional blocks.

(1 and 2 differ only in the way a file is coded, the preprocessor is actually the same.)

The problem is, there's no option to have valid CSS + CSS variables + conditional blocks. The way I see it, it is the most clean option and should be used by default. Addition of at-rule syntax to defaut/USO preprocessor is guaranteed to not break anything.

Considering almost everything is already implemented (if statements, CSS parsing), adding a new syntax shouldn't be difficult. I guess I can make a pull request myself.

Mottie commented 6 years ago

I'm confused, how does valid CSS include conditional blocks?

The USO preprocessor can only use conditional blocks within the @var, not within the CSS.

We're not using SASS or LESS because the libraries to parse CSS are ginormous; and the Stylus preprocessor appears to be adequate for what you need. So, why are you compelled to need a new @ rule?

Mottie commented 6 years ago

I'm not against the idea 😸 , but I don't have the final say in the decision.

And to answer the other questions:

Pure CSS @var... Is that the correct approach?

Yes, including a duplicate default within the var() would work, but you wouldn't need to unless you're definitely planning on using the style in other style managers. The preprocessor to add default var() and replace USO style placeholders is built-in.

Our implementation does support the freestyler extension's method of setting advanced options.

Workflow

Stylus has a vastly improved and updated version of the style editor - you can still use the same workflow. Edit the style in a separate window and then saving the changes will automatically update the userstyle in any targeted tabs.

Ideally, I'd like to write pure CSS, with support for options in all user style extensions

That would be difficult since Stylish doesn't support option modification from within the extension - but I haven't checked the latest update. It would be nice to have a standard, but there are too many maintained and un-maintained style extensions out there to try to coordinate.

Adding a @-styl-if wouldn't fix this problem, unless you can convince the other style extension authors to also include the conditional block.

I guess I can make a pull request myself.

Please do, we're always looking to get help from more contributors!

Athari commented 6 years ago

@Mottie My proposal is a valid CSS proprietery extension. If you add it, nothing breaks, a valid CSS file remains a valid CSS file β€” that's what I mean by valid extension. It's just another conditional block like @supports or @media.

The reason I want it is that currently, if I need conditional blocks, I have to choose between two options:

  1. USO syntax which requires me to put CSS code into comments. This is a bad idea: I lose syntax highlighting, I lose validation, I lose instant preview etc.
  2. Stylus syntax which forces me to use unprefixed variables, which in turn makes my CSS invalid. Less bad idea, but still: lost validation, relience on specific software just to preview results etc.

The way I see it, adding prefixed @if rule to USO preprocessor would be low effort and low bloat:

  1. the code to work with if statements already exists in Stylus preprocessor, can be simply reused;
  2. CSS is already parsed for at-rules, so it's as simple as treating one at-rule as an if block from another parser (if condition { block } => @-styl-if (condition) { block }).
Athari commented 6 years ago

Adding a @-styl-if wouldn't fix this problem, unless you can convince the other style extension authors to also include the conditional block.

I'm not writing styles as epic as GitHub-Dark, which heavily rely on configuration, so I can afford to say in the description something like: "When installed, you get all options set to default. If you want to configure the style, use Stylus extension or edit variables manually." (I already use CSS variables heavily.)

It also kinda opens a possibility for converting between formats automatically. Having all information in one file is the first step, valid CSS simplifies it. At one point I'll probably write a user script which converts user.css to USO when copy-pasted to userstyles.org's textbox (that would put strict limitations on if statements, but can be done).

tophf commented 6 years ago

If you want to configure the style, use Stylus extension or edit variables manually

That would disable updates for this style because it'll be considered locally modified and we protect local modifications for the obvious reason of protecting them. So I'm not sure this entire idea is worth implementing. Or do you mean Stylus will act as a preprocessor to compile the style code to use variables customized in the style config dialog? But then it'll suffer from the same predicament you cited as a SERIOUS PROBLEM - it needs a preprocessor.

Athari commented 6 years ago

styl is a file extension for the stylus-lang preprocessor so I think you should invent something else for the at-rule name.

@tophf File extensions and vendor CSS prefixes aren't exactly related, so there's no conflict. It can be kinda confusing though, I agree.

I just wanted something short, related to Stylus-as-addon, yet generic enough and related to styles in general. "Styl" seemed like a good candidate.

Browsers use company and web engine names as prefixes. What's "OpenStyles" which is used as a company name on GitHub?

So... Let's see what options we have.

If -styl- is unacceptable, then I'm leaning towards -user-, as I would feel natural using it in a .user.css file. Second best is probably -userstyle-.

Or do you mean Stylus will act as a preprocessor to compile the style code to use variables customized in the style config dialog?

Yes. The .user.css files using this syntax should work correctly in any extension, but will have additional config functionality in Stylus. (And if a user decides to, they can manually edit a style, losing update functionality β€” some websites are updated once in a decade, so it isn't that bad actually.)

Hmm, need to test userstyles.org's parser. It failed parsing advanced grid-template-columns syntax and disallowed uploading. I reported a bug. but no response so far. There's a chance its CSS parser isn't compliant with regards to unrecognized at-rules too.

tophf commented 6 years ago

What about @-if?

Athari commented 6 years ago

@tophf That would violate the standard.

tophf commented 6 years ago

@-use-if? @-apply-if? etc. I just want it to be a real word, not styl as it looks weird.

Mottie commented 6 years ago

Would this also include an implementation of @-???-else?

Athari commented 6 years ago

@tophf This prefix is supposed to identify the vendor, not just be something random. It's also supposed to be applied to all extensions of the vendor, so if any other CSS syntax specific to Stylus / user styles is invented later, the same prefix should be used.

It doesn't have to be a real word. Compare to -moz-, -ms-, -webkit-, -khtml- etc.

@Mottie CSS at-rule syntax doesn't allow multiple at-rule sections to be combined, AFAIK. That's not a problem though, you can always just negate the condition. I think most of the uses should be equality tests @if (dropdown-option == "Value 1") { ... } anyway.

Mottie commented 6 years ago

I'd vote for @-check-if then; hmm, but @-use-if is much shorter πŸ˜›

Athari commented 6 years ago

@Mottie Let's imagine we want to add another two rules to Stylus some time later: @foreach rule for cycles and @browser rule for some browser checks.

Would @-check-foreach be an appropriate name? Probably not. It has nothing to do with checks. This is because check is tied to only one at-rule, @if. Vender prefixes, however, are supposed to be tied to vendors, not to features, hence the name. πŸ˜‰

Would @-use-browser be appropriate? It'll probably confuse lots of people because the verb stands out as if it's a meaningful part of the name.

Ideally, we want a prefix which is tied to user styles in general. This is why I lean towards -user- prefix: user styles, user scrpits, user at-rules, there's a pattern here.

P. S. Yup, there are only two hard things in Computer Science. πŸ˜†

tophf commented 6 years ago

@-user-if is good.

eight04 commented 6 years ago

Feature request: @if any conforming CSS parser from the past, present or future, will correctly skip this as an unrecognized at-rule

I don't think it is worth re-inventing another preprocessor just because we want to make the code compatible with other CSS parsers.

  1. It doesn't introduce any new feature comparing to other mature ones.
  2. It can only be used in the extension.
  3. Authors have to learn a new syntax to use it.
  4. This syntax would only work with variables defined in the usercss header, not actual CSS variable i.e. it won't evaluate dynamically when the variable is overwritten by cascading/inheritance.

Question: Pure CSS @var This way, CSS file works correctly both as a stanalone file and with GUI support. I don't like value duplication

I suggest creating a build tool that can extract CSS variables from usercss header and inject them to the usercss file to create a standalone version. Note that the standalone version might not work after Firefox 61 since the built-in @-moz-document rule has been disabled.

I'd like to write pure CSS, with support for options in all user style extensions, as well as easily update online versions

Mottie commented 6 years ago

Related: https://tabatkins.github.io/specs/css-when-else/