Last modified: 2014-11-20 01:12:30 UTC

Wikimedia Bugzilla is closed!

Wikimedia migrated from Bugzilla to Phabricator. Bug reports are handled in Wikimedia Phabricator.
This static website is read-only and for historical purposes. It is not possible to log in and except for displaying bug reports and their history, links might be broken. See T63440, the corresponding Phabricator task for complete and up-to-date bug report information.
Bug 61440 - CSSJanus fails to flip with !important
CSSJanus fails to flip with !important
Status: RESOLVED FIXED
Product: MediaWiki
Classification: Unclassified
ResourceLoader (Other open bugs)
1.25-git
All All
: Low normal (vote)
: ---
Assigned To: Matthew Flaschen
: upstream
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2014-02-16 15:27 UTC by Niklas Laxström
Modified: 2014-11-20 01:12 UTC (History)
8 users (show)

See Also:
Web browser: ---
Mobile Platform: ---
Assignee Huggle Beta Tester: ---


Attachments

Description Niklas Laxström 2014-02-16 15:27:10 UTC
Here is an example test case which fails:

			array(
				'.foo { margin: 1px -4px 3px 2px !important; }',
				'.foo { margin: 1px 2px 3px -4px !important; }'
			),
Comment 1 Bartosz Dziewoński 2014-02-16 15:41:20 UTC
Hm. There are a few cases where we regex for '[;}]', we should extend that to something like '(?:!important\s*)?[;}]'.
Comment 2 Gerrit Notification Bot 2014-02-16 15:51:30 UTC
Change 113667 had a related patch set uploaded by Nikerabbit:
Workaround for CSSJanus bug 61440

https://gerrit.wikimedia.org/r/113667
Comment 3 Gerrit Notification Bot 2014-03-05 16:47:30 UTC
Change 113667 merged by jenkins-bot:
Workaround for CSSJanus bug 61440

https://gerrit.wikimedia.org/r/113667
Comment 4 Matthew Flaschen 2014-10-08 23:40:27 UTC
Thanks, Bartosz.  I submitted a fix (https://github.com/cssjanus/php-cssjanus/pull/3) upstream using your regex change.  I also added a few tests.
Comment 5 Krinkle 2014-10-09 01:48:32 UTC
Note that !important must never be used. It is a valid bug for upstream CSSJanus (since it's valid CSS), but should not bare any relevance to code in Wikimedia environments.

There is not a single valid use case for using !important (with the exception of working around upstream code running on the same page that also uses !important, because only !important can trump !important).

Any other case, and I mean, *any* other case, has other solutions that are better. Using !important breaks cascading nature and is simply unneeded infectious overkill. Consider it similar to other bad coding patterns that should be disallowed by convention (like using the @-operator in PHP, or loose == comparison and automatic semi-colon insertion in JavaScript).

Using irrelevant selectors (as Ic5c575068d911 did) is not necessary. In most cases it's  just unnecessary to begin with (e.g. unjustified paranoia). In other cases it may be result of a bug elsewhere in the code.

To override a style, always use the same selector as the original style and you'll be fine.

If your code is loaded before the other code, something is wrong. If that wrong thing can't be fixed, try harder. Eventually, you may want to resort to one of few workarounds, such as:
* Repeat the same selector to increase weight, like .foo.foo.foo.foo
  (however much weight you need), still leaves you in a better environment than important by allowing multiple code paths to use the same technique and control their weight.
* Add [class] selectors (less heavy).
* Use default elements as ancestor selector ("body .foo", "html body .foo"). Better than adding in random ancestors that are not relevant to your code. And more maintainable as these don't change.

Anything but !important.

-- Krinkle

[1] 3.14 things you didn't know about CSS: http://vimeo.com/100264064
Comment 6 Krinkle 2014-10-09 02:14:31 UTC
Thanks Siebrand. I've put it here:
https://www.mediawiki.org/wiki/Manual:Coding_conventions/CSS#.21important
Comment 7 Matthew Flaschen 2014-10-09 07:36:11 UTC
(In reply to Krinkle from comment #5)
> To override a style, always use the same selector as the original style and
> you'll be fine.

That isn't appropriate in all cases.  Say there are rules for a fooSelector elsewhere.  You want to style barSelector.  Either "barSelector elements" is a subset of "fooSelector elements", or the sets intersect.

In the case of a conflict, you want to override the rules associated with fooSelector.

Simply using fooSelector again is not correct.  It can unintentionally re-style elements you want to leave alone.

If they are overlapping sets, it will also omit elements you *do* want to style (things that are barSelector but *not* fooSelector)

However, it's true that adding specificity usually works well in these scenarios.  Sometimes this can be done naturally, e.g. with a meaningful container element:

.bar-root barSelector

However, as you said, !important is part of CSS, whether we like it or not, and it needs to work properly (including in our version).

Note, I've ported it to to the JavaScript repo now (https://github.com/cssjanus/node-cssjanus/pull/27)
Comment 8 Krinkle 2014-10-09 10:15:23 UTC
(In reply to Matthew Flaschen from comment #7)
> (In reply to Krinkle from comment #5)
> > To override a style, always use the same selector as the original style and
> > you'll be fine.
> 
> That isn't appropriate in all cases.  Say there are rules for a fooSelector
> elsewhere.  You want to style barSelector.  Either "barSelector elements" is
> a subset of "fooSelector elements", or the sets intersect.
> 
> In the case of a conflict, you want to override the rules associated with
> fooSelector.
> 
> Simply using fooSelector again is not correct.  It can unintentionally
> re-style elements you want to leave alone.
>

I'm not convinced. Poke me on IRC with an example.
Comment 9 Matthew Flaschen 2014-11-14 20:05:51 UTC
Step 1 is done.  It's fixed in the CSSJanus upstream node.js repository.  However, I realized we also need to do a node.js release and tag, since the PHP version imports the tests by tag: https://github.com/cssjanus/php-cssjanus/blob/master/test/suites/CSSJanusTest.php#L55 .

node.js change to set up the release: https://github.com/cssjanus/cssjanus/pull/30

Updated version of the PHP pull request (node.js release needs to be finished before this can be merged, and that's what's causing Travis to fail): https://github.com/cssjanus/php-cssjanus/pull/3 

Note, this impacts Flow, but we will be changing the affected area not to use !important in addition to this fix.
Comment 10 Matthew Flaschen 2014-11-19 21:00:04 UTC
(In reply to Matthew Flaschen from comment #9)
> node.js change to set up the release:
> https://github.com/cssjanus/cssjanus/pull/30

Krinkle tweaked and merged this.

> Updated version of the PHP pull request (node.js release needs to be
> finished before this can be merged, and that's what's causing Travis to
> fail): https://github.com/cssjanus/php-cssjanus/pull/3

This is the last remaining item in the CSSJanus repos (after this, we just need to bump core's composer.json).  Since the node.js change has been merged (the tests are imported from the node.js repo), it's now passing.
Comment 11 Gerrit Notification Bot 2014-11-19 23:39:16 UTC
Change 174593 had a related patch set uploaded by Krinkle:
resourceloader: Update cssjanus to v1.1.1

https://gerrit.wikimedia.org/r/174593
Comment 12 Gerrit Notification Bot 2014-11-20 01:02:18 UTC
Change 174593 merged by jenkins-bot:
resourceloader: Update cssjanus to v1.1.1

https://gerrit.wikimedia.org/r/174593

Note You need to log in before you can comment on or make changes to this bug.


Navigation
Links