Page MenuHomePhabricator

Allow template parameters to provide CSS to a templatestyles stylesheet
Open, Needs TriagePublic


There are a large number of templates where a specific style property (e.g. width) is provided a template parameter (usually that's just because it was the most likely to be needed; sometimes because the template designers deliberately restricted users from entirely arbitrary styles, most-likely because most Wiki*ians are not technical people, probably). Unlike e.g. the float + margin combination, which has essentially an enumerated value set (and which could ostensibly have classes for e.g. left, right, and center), width has many possible values, such that it would be difficult or impossible to provide a class.

An example might be Template:Collapse. I can extract to templatestyles a few properties styled on the table currently (display, some of the float-related properties e.g. margin, float, clear; text-alignment). What I cannot do is extract the width property required for floating one of these tables. Other cases on that particular template I can't extract are the various background colors, border-color (on the table element), and so forth.

I'll be sure to extract the properties I can. However, might there be some way to pass TemplateStyles the value of the width parameter?

Event Timeline

I have a set of 'monster' templates at English Wikisource , cl-act-paragraph (and related) , which currently use a considerable amount of inline CSS, or parameter passing via various levels of template... What differs between the templates is typically trivial details such as left/right or the amount of indentation.

Simplifying this down to use 'templated' CSS might be simpler and easier to maintain ( portions were already re-worked to use Lua)., so the ability to have parameters to a common CSS core would be useful.

Let's look at an example. If this feature existed, it might look something like this:

Template:Box/styles.css {
    border: 1px solid -mw-var( color );
{{#tag:templatestyles|| src=Box/styles.css | color={{{color}}} }}
<div class="box">{{{text}}}</div>

So then you could write wikitext like

{{box|color=blue|This is in a blue box!}}

That seems ok, until you try to use it more than once with different colors:

{{box|color=blue|This is in a blue box!}}
{{box|color=red|This is in a red box!}}

The generated HTML would look something like this:

<style> {
    border: 1px solid blue;
<div class="box">This is in a blue box!</div>
<style> {
    border: 1px solid red;
<div class="box">This is in a red box!</div>

That's not going to work. The rule in the second <style> tag will override the first and both boxes will be red. Deduplication, if it doesn't take into account the parameterization, might instead remove the second instance leaving both boxes blue.

CSS does provide a way around this in the CSS Custom Properties for Cascading Variables Module Level 1 (which is currently supported by about 87% of browsers)

<style> {
    border: 1px solid var(--color, green);
<div class="box">Green box</div>
<div class="box" style="--color:red">Red box</div>
<div class="box" style="--color:blue">Blue box</div>
<div style="--color:orange">
 <div class="box">Orange box</div>
 <div class="box">Also an orange box</div>

The trick would be to make sure that someone can't write something like this

<style> {
    border: 1px solid var(--color, green);
    background: var(--bg, white);
<div class="box">Green box</div>
<div class="box" style="--color:red">Red box</div>
<div class="box" style="--color:blue; --bg:purple">Blue box with a purple background</div>


<div class="box" style="--bg:url('http://evil.example/tracker.png')">Uh oh, privacy violation</div>

also works with that example. That particular example wouldn't work in MediaWiki because MW forbids "url(" in inline style attributes, but css-sanitizer and TemplateStyles shouldn't rely on that.

We might allow it for only some safe properties, versus the "allowed anywhere" model described in the standard. Although even that would rely on no browser deciding to extend the syntax of a safe property in a way that opens some security hole.

On an aside, this request was also made on T155813: Decide on storage and delivery method for TemplateStyles CSS (there may be other discussion related in that task; I just happened to be reading it because of the discussion about TemplateStyling Template:Documentation):

Make the system flexible enough that editors are willing to replace most existing templates. IMO this means some sort of template parameter passing - there are way too many complex templates that take arguments for color, width, float direction etc. I guess colors could be kept as inline styles (they aren't really device-dependent), and the rest can be handled by classnames (and specifying width is a bad idea in the first place)? But it would be nice if there was an explicit way to pass settings to the CSS code. Since 1A/C has been excluded in the previous bullet point, that would imply 2C in which case the parser tag could be used with {{#tag}} to take parameters. How would it work with the CSS parsing though? (We want to parse when the page is saved, to have sane error handling.) So I guess this goal is infeasible no matter what.

I will note that CSS3 also apparently supports an attr() function as well.

This coupled with tag: might be a way to generate 'safe' CSS stylesheets in the desired manner once browsers support it...

I will note that CSS3 also apparently supports an attr() function as well.

attr only exists in the spec.

ShakespeareFan00 changed the task status from Open to Stalled.May 11 2020, 7:53 AM

attr() is as you correctly indicate , not widely supported at all.

I am therefore marking this task as 'Stalled' until browser support catches up.

This task is not about attr() support though.

Aklapper changed the task status from Stalled to Open.May 11 2020, 11:31 AM

Resetting task status as this task is not about attr() support

That particular example wouldn't work in MediaWiki because MW forbids "url(" in inline style attributes, but css-sanitizer and TemplateStyles shouldn't rely on that.

Hmm. Shouldn't they though? I'm all in favour of reducing dependencies and applying layered security, but given what the architecture actually is currently, isn't the correct approach to handle it through MW's allowable parameter value filter and allow e:TemplateStyles to rely on that?

It's not necessarily that that is a particularly elegant solution for a greenfield implementation, but given the filtering has to happen when the wikitext page is saved I don't really see how any other approach is even feasible.

I've added a contrived test-case here:-

For when is resolved and var() support is re-enabled for CSS on test wiki.

The CSS sanitizer doesn't currently recognise var() constructions as valid though...