stylus: Stylus should not overwrite CSS built-in functions, such as min and max
In CSS, there are built-in functions, such as min and max. Unfortunately, Stylus has the exactly same built-in functions, That’s bad and error prone.
I wanted to write a CSS max to responsively, dynamically calculate the height of an image from the current view port:
.myclass
height: max(30vh, 50vw)
But it did not work as expected. After quite some time and debugging the generated CSS-code and then searching the Stylus docs, I found out, that Stylus has an internal function of the same name maxthat is called here.
So, stylus produced the following output:
.myclass {height:50vw;}
This is crazy stupid! Stylus cannot know the size of 1vw nor 1vhat compile time! It should at least abort with an error, instead of silently producing rubbish!
So,to solve my problem, I finally got the correct result with the following work-around:
.myclass
height: @css{max(30vh, 50vw)}
Please rename or remove the Stylus functions max and min, and any other Stylus function that shadows a CSS built-in function!
Why not prepend all Stylus built-in functions with a prefix, such as stylus_min, __min or _min?
About this issue
- Original URL
- State: open
- Created 3 years ago
- Reactions: 16
- Comments: 25 (2 by maintainers)
Stylus should just rename these specific functions, e.g. prepend ‘stylus-’ to them. Projects have to adapt. Which is not difficult, just run a regular expression over the files.
Good catch, and a use case I certainly hadn’t thought about!
Personally though, I prefer the dry syntax philosophy of Stylus, which would somewhat be undermined by some Stylus-specific prefix to memorise for some or all BIFs. Not to mention the problems around renaming BIFs now, when thousands of existing Stylus-based projects may rely on these being BIFs rather than CSS4 functions.
One solution could be to detect whether a
min()andmax()function contains run-time units likevwandvh, and return a CSS literal when it does, or compile it as a Stylus BIF when it doesn’t.Another solution which could give the author more certainty about expected behaviour would be to have a more compact CSS literal syntax, maybe with backticks (`)?
Would either of these be useful to you?
@vendethiel wrote:
I see. Interestingly, the feature is already well supported in most browsers.
In that case, what about an upgrade of Stylus with regard to CSS4?
BTW, future changes of the standard and compiler specific extensions are the reason, why in C/C++, it is best practice to prepend precompiler macros with a prefix. I suggest to do the same here.
@nilslindemann
Yes, and all these suggestions, I mean that
someFn()is always the CSS built-in, and the Stylus fn would be some of:$someFnorsomeFn!()orstylus.someFn(), is a Stylus major version bump, right. — So one could do these regex-replace when one had time (and not get a minor version bump major surprise :- ))@disco0
I like that idea. I think it should work the other way around: Stylus functions should get a
!suffix. Otherwise the original problem will remain — that Stylus unexpectedly does something different, when one typesmax(), than what one thought.Because, if someone writes
max(...)orcalc(...), they typically have in mind the CSS built-in, not the Stylus function.Like @nilslindemann wrote:
***
someFunc!(...)is the approach Rust has taken for macros, and … apparently!works fine in their case.someFunc!(...)looks pretty nice too, syntax highlighting wise? With the!in a bit red / different color. Maybe there could be a Stylus color scheme recommendation that the!should be bold / a bit different color. So it was easy to notice.Personally I like all of
$someFn(...)andsomeFn!(...)andstylus.someFn(...). (And letting justsomeFn()be the CSS built-in.)@kajmagnus, prepending
$sounds good to me. I’d recommend some kind of prefix for built in Stylus functions, that prevents also conflicts with future CSS standards.It helps me to write things side by side, just looking at them.
So here is an overview of the suggestions made so far, in order of appearance per category. The first is the Stylus call, the second the CSS call. “+” denotes my preference (which is not hard science).
These work currently:
max(30vh, 50vw)vs@css{max(30vh, 50vw)}+max(30vh, 50vw)vs"max(30vh, 50vw)" % nullmax(30vh, 50vw)vs"max(30vh, 50vw)" % ()These change the CSS call:
max(30vh, 50vw)vs`max(30vh, 50vw)`+max(30vh, 50vw)vs[max(30vh, 50vw)]max(30vh, 50vw)vs@css max(30vh, 50vw)max(30vh, 50vw)vsmax!(30vh, 50vw)max(30vh, 50vw)vs_max(30vh, 50vw)These change the Stylus call:
stylus_max(30vh, 50vw)vsmax(30vh, 50vw)__max(30vh, 50vw)vsmax(30vh, 50vw)_max(30vh, 50vw)vsmax(30vh, 50vw)$max(30vh, 50vw)vsmax(30vh, 50vw)+math.max(30vh, 50vw)vsmax(30vh, 50vw)stylus-max(30vh, 50vw)vsmax(30vh, 50vw)max!(30vh, 50vw)vsmax(30vh, 50vw)+stylus.max(30vh, 50vw)vsmax(30vh, 50vw)+Max(30vh, 50vw)vsmax(30vh, 50vw)MAX(30vh, 50vw)vsmax(30vh, 50vw)+Other possibilities:
max(30vh, 50vw)vsmax(30vh, 50vw)(call the proper function based on parameters)@vendethiel we know that Sass went this route, but I believe it is potentially confusing.
Hello,
Where are we ? Can we hope to see these compatibility problems that accumulate between Stylus and modern CSS corrected?
I dug around a bit in the Stylus files, min() max() is here, but generally speaking all functions should be renamed. It would not be very difficult to start all over again (but time-consuming no doubt) and Stylus would become compatible with the future rules.
Of course, such a backward compatibility-breaking change would be the subject of a new major release. However, I think that this evolution is essential: not respecting the standard CSS as valid in Stylus is a certain guarantee for the death of the project.
We could also prefix with an underscore, which would be a quick and easy change:
Indeed, I don’t think that CSS functions are ever pefixed with an underscore, however I think that would correspond well to the spirit of the Stylus syntax.
This would be very welcome improvement for css functions in general—after some experiments in the past with
calcI now usually just end up writing sprintf operators like @nilslindemann (ps:"calc(...)"%()also works, believe this is the shortest form).Haven’t looked at the parser code in a long time, and I don’t remember how whitespace is handled between a function identifier and its call parens, but how difficult would it be to handle css builtin function calls with a
!postfix (or maybe the other way around)? e.g.:I like the separation—it’d be pretty explicit what you mean, and (at least for now, using normal function declaration syntax,) it’d be impossible to declare a similar
<ident>!style function which is a nice, if not maybe overkill, namespacing. Its also entirely isolated from other identifiers unlike a$sigil orstylus-prefix (the former of which I use on all my variables, so not my pick here). Otherwisemathprobably works@groenroos
Personally I like
@css{ ... }better,because 1) also readers not yet that familiar with Stylus, understand what it means. Whilst a backtick — I might have thought that 2) it got copied literally to the generated CSS, and might have wanted to remove it. After all,
"..."is copied as is (the quotes intact, get copied too, right). And 3) maybe a future CSS feature will make use of backticks in some way? Which would then collide with Stylus.Seems like a more complex solution to me. Then, if min & max somehow didn’t do what I hoped, I’d need to wonder if maybe maybe there was something wrong with Stylus’ heuristics for computing or keeping-as-is
min(..)andmax(..). Might break if new CSS versions introduce new units.@mwaeckerlin
I like that idea. What about Stylus 4.0 for CSS 4+, where all built-in Stylus functions and names were prefixed by
$. So it’d be$maxand$min. But of course (?) it must still be possible for Stylus utility libraries or application specific Stylus styles, to define one’s own functions without$:- )stylus_minis OK too — doesn’t look so nice, but is new-developer-friendly, & better than bugs :- ) — I just noticed, after some weeks, thatmin(...)had been computed & removed by Stylus, and was absent in my web app.