Reputation: 124
I declared display: inline
on body
but the elements are still displayed in block fashion. Please help me understand the concept.
Declaring display: inline
directly on li
works: They will display in inline fashion. But why doesn't inline apply to them when declaring on body
?
body {display: inline}
<body>
<ul>
<li>1234</li>
<li>5678</li>
</ul>
</body>
I also tried with display: inherit
on li
, but it still displays in block fashion, and also removes the markers which I don't want:
body {display: inline}
li {display: inherit}
<body>
<ul>
<li>1234</li>
<li>5678</li>
</ul>
</body>
Upvotes: 1
Views: 71
Reputation: 3434
display
Setting display
on an element will not have its children inherit the value:
.wrapper {display: inline}
<div class="wrapper">
<div>First text.</div>
<div>Second text.</div>
</div>
While you can declare elements to inherit display
from their ancestors, I do not recommend this (generally):
display
requires a declaration just as much as declaring a specific display
value.It is important to choose good selectors for your use case. For your short example it is fine to have a generic selector, like body *
(in words: "All descendants of BODY
") which uses the universal selector *
and a descendant combinator
.
Note: Using a combinator generally does not select "sub-selections" itself, e.g. BODY
of selector body *
will not be selected. Also note that the descendant combinator is less specific than the child combinator >
.
Here is an analogous example:
.wrapper * {display: inline}
<div class="wrapper">
<div>First text.</div>
<div>Second text.</div>
</div>
If however you still want to declare the elements to inherit display
, here is an example:
.wrapper {display: inline} /*Set the value to inherit*/
.wrapper * {display: inherit}
<div class="wrapper">
<div>First text.</div>
<div>Second text.</div>
</div>
display
Lists' default display
value is block
, and the value of its children
(LI
) is list-item
. If you simply want to get rid of the markers, declare the list list-style-type: none
:
ul {list-style-type: none}
<ul>
<li>First item.
<li>Second item.
</ul>
But you can also declare the list and its children (ul, ul>*
) as display: inline
. Note that removing padding requires another declaration.
ul, ul>* {display: inline}
<ul>
<li>First item.
<li>Second item.
</ul>
If you want to inline the list-items with markers, there are several possibilities:
You can keep ::marker
s of inline list-items by declaring the list as display: inline-flex
.
Sidenote: ::marker
s are by default outside
the list-item's principal box, which means they can obstruct view of other boxes. Declare the list (or its items) as list-style-position: inside
to keep the markers inside the list-item's box to prevent such overflow.
Note that flex-wrap: nowrap
is its default, which is unlike regular text flow. Use flex-wrap: wrap
to have the list-items (and their content) flow like regular text:
// Ignore; for handling radio inputs
const form = document.querySelector("form");
const list = document.querySelector("ol");
form.addEventListener("input", evt => {
const className = evt.target.name === "position" ? "inside" : "wrap";
// Classes for applying non-default values are named after the values
const state = evt.target.value === className;
list.classList.toggle(className, state);
});
ol {display: inline-flex}
.inside {list-style-position: inside}
.wrap {flex-wrap: wrap}
/*Ignore; for presentational purposes*/
ol {margin: 0; padding: 0}
li {border: 1px solid darkgray}
section {margin-block: 1.2rem}
<form>
<div>
List type:
<label for="i-outside">
<input id="i-outside" name="position" type="radio" value="outside" checked> Outside
</label>
<label for="i-inside">
<input id="i-inside" name="position" type="radio" value="inside"> Inside
</label>
</div>
<div>
Wrapping:
<label for="i-nowrap">
<input id="i-nowrap" name="wrap" type="radio" value="nowrap" checked> No-wrap
</label>
<label for="i-wrap">
<input id="i-wrap" name="wrap" type="radio" value="wrap"> Wrap
</label>
</div>
</form>
<ol>
<li>A very long named item that hopefully overflows its box, and
<li>An item, and
<li>Another short item, and
<li>another very long named item that too should overflow its box.
</ol>
You can also use custom "markers" via the ::before
pseudo-element.
Sidenote: With a custom-styled CSS counter, you can recreate e.g. list-style-type: georgian
counters:
ol {counter-reset: li-counter}
li {counter-increment: li-counter}
li::before {content: counter(li-counter)". "}
/*Ignore; for presentational purposes*/
ol, li {padding: 0; display: inline}
A list consisting of
<ol>
<li>one item and
<li>another item.
</ol>
display
?You asked why the following didn't result in the LI
s to inherit the BODY
's display
value:
body {display: inline}
li {display: inherit}
<body>
<ul>
<li>First item.
<li>Second item.
</ul>
</body>
That is because—while BODY
is declared as display: inline
—the list in between has the default display
value of block
. Since inheritance happens from the element's immediate ancestor, the list-items will inherit the value block
from the list.
Lists are semantic elements, and by default are interpreted as such by the browser. But changing their styles may change how the browser interprets them, potentially reducing their semantic down to a generic text-containing element.
Therefore it is generally good to ensure that lists are interpreted as lists by declaring the list and its items via the ARIA-attribute role
as list
and listitem
, respectively. This overrules the browsers decision to interpret the element as a list, even if the browser would have decided not to interpret it as a list because of some CSS.
Another point is that pseudo-elements (e.g. ::marker
, ::before
) are technically not part of the document, and can therefore not be interacted with (e.g. selecting or copying). If you need them as part of the document, then literally include them in the document.
Upvotes: 2