1/**
2 * These rules prevent re-flows relating to collapsible on-wiki elements (T42812).
3 * This is done by temporarily creating a pseudo element in the place that JavaScript will insert
4 * a toggle control. The same CSS rules that control the positioning of the toggle control will apply
5 * to the pseudo element. When the JavaScript has executed
6 * (See corresponding non-render blocking CSS in jquery.makeCollapsible)
7 * all pseudo elements will be removed.
8 *
9 * Currently we support all the examples on [[mw:Manual:Collapsible_elements/Demo/Simple]]
10 * All examples on [[mw:Manual:Collapsible_elements/Demo/Advanced]] are supported with the following
11 * exceptions
12 * - Custom collapsible 4 (table-row)
13 * -- CSS selector would be too complicated
14 * - Collapsible div nested in collapsed div
15 * -- Given it's not easy to identify the collapsed content via CSS, text will be shown until
16 *    JavaScript has loaded
17 * - "Combination example"
18 * -- At a later time, we may want to support the use of of `attr`, but given the code
19 *    complexity we will not for the time being (see https://davidwalsh.name/css-content-attr)
20 */
21
22// This selector is used frequently in the code to indicate that the JavaScript has successfully completed
23// it's execution and pseudo elements can be disabled. For readability and maintainability it is separated
24// as a LESS variable.
25@exclude: ~'.mw-made-collapsible';
26
27.client-js {
28	ol.mw-collapsible:before,
29	ul.mw-collapsible:before,
30	.mw-collapsible-toggle-li {
31		/*
32		 * Rather than inherit any margins from the general li selector - make sure this is explicit
33		 * to avoid reflows
34		 */
35		display: list-item;
36		list-style: none;
37		margin-bottom: 0.1em;
38	}
39
40	// Reset when mw-collapsible-toggle-li is rendered
41	ol.mw-made-collapsible:before,
42	ul.mw-made-collapsible:before {
43		display: none;
44	}
45
46	// table.: Where the tbody or thead is the first child of the collapsible table
47	ol.mw-collapsible:not( @{exclude} ):before,
48	ul.mw-collapsible:not( @{exclude} ):before,
49	table.mw-collapsible:not( @{exclude} ) :first-child tr:first-child th:last-child:before,
50	table.mw-collapsible:not( @{exclude} ) > caption:first-child:after,
51	div.mw-collapsible:not( @{exclude} ):before {
52		content: '[@{msg-collapsible-collapse}]';
53	}
54
55	td.mw-collapsed:not( @{exclude} ):before,
56	table.mw-collapsed:not( @{exclude} ) :first-child tr:first-child th:last-child:before,
57	table.mw-collapsed:not( @{exclude} ) > caption:first-child:after,
58	div.mw-collapsed:not( @{exclude} ):before {
59		content: '[@{msg-collapsible-expand}]';
60	}
61
62	// Any element with id beginning `mw-customcollapsible` will have special treatment
63	.mw-collapsible[ id^='mw-customcollapsible' ] th:before,
64	.mw-collapsible[ id^='mw-customcollapsible' ]:before {
65		content: none !important; // stylelint-disable-line declaration-no-important
66	}
67
68	// Special case for table where first child is caption element
69	table.mw-collapsible:not( @{exclude} ) > caption:first-child:after {
70		float: none;
71		display: block;
72	}
73
74	// Use the exclude selector to ensure animations do not break
75	.mw-collapsed:not( @{exclude} ) {
76		// Avoid FOUC/reflows on collapsed elements by making sure they are opened by default (T42812)
77		// > thead + tbody: 'https://www.mediawiki.org/wiki/Manual:Collapsible_elements/Demo/Simple#Collapsed_by_default'
78		> p,
79		> table,
80		> thead + tbody,
81		tr:not( :first-child ),
82		.mw-collapsible-content {
83			display: none;
84		}
85	}
86}
87
88/* Collapsible elements in the UI (outside of the content area) are not in either .mw-content-ltr or
89 * .mw-content-rtl. Align them based on the user language. */
90.mw-collapsible:not( @{exclude} ) th:before,
91.mw-collapsible:not( @{exclude} ):before,
92.mw-collapsible-toggle {
93	float: right;
94}
95
96/* For collapsible elements in the content area, override the alginment based on the content language. */
97/* @noflip */
98.mw-content-ltr,
99.mw-content-rtl .mw-content-ltr {
100	.mw-collapsible:not( @{exclude} ) th:before,
101	.mw-collapsible:not( @{exclude} ):before,
102	.mw-collapsible-toggle {
103		float: right;
104	}
105}
106
107/* @noflip */
108.mw-content-rtl,
109.mw-content-ltr .mw-content-rtl {
110	.mw-collapsible:not( @{exclude} ) th:before,
111	.mw-collapsible:not( @{exclude} ):before,
112	.mw-collapsible-toggle {
113		float: left;
114	}
115}
116
117/* list-items go as wide as their parent element, don't float them inside list items */
118li,
119.mw-content-ltr li,
120.mw-content-rtl li,
121.mw-content-ltr .mw-content-rtl li,
122.mw-content-rtl .mw-content-ltr li {
123	.mw-collapsible-toggle {
124		float: none;
125	}
126}
127
128// special treatment for list items to match above
129// !important necessary to override overly-specific float left and right above.
130ol.mw-collapsible:not( @{exclude} ):before,
131ul.mw-collapsible:not( @{exclude} ):before {
132	float: none !important; // stylelint-disable-line declaration-no-important
133}
134