Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at Scotch On The Rock (SOTR) 2010 (Brussels) with: Ray Camden
Ben Nadel at Scotch On The Rock (SOTR) 2010 (Brussels) with: Ray Camden@cfjedimaster )

Revisiting: Styling A Movie Cast List Using A Definition List And Flexbox

By Ben Nadel on
Tags: HTML / CSS

The other day, while basking in the awesome power of Flexbox, I took a stab at trying to style a movie cast list using a Definition List and CSS Flexbox. My approach used a pseudo-element and nested flexbox containers, which worked well. But, in response to my post, Ilya Streltsyn and Sime Vidas both came up with interesting ways simplify the CSS. And, since I've never used either of the techniques that they provided, I wanted to quickly revisit the post and share with you the solutions that they shared with me.

Run this demo in my JavaScript Demos project on GitHub.

View this code in my JavaScript Demos project on GitHub.

To quickly recap, my solution used a Definition List in which the DT element implemented a nested Flexbox container. My "dots" where then defined as a pseudo-element inside of the nest container, with a flex-grow of 1 that would consume all of the free space:

Nested flexbox strategy for rendering a movie cast list.

This worked perfectly well; but, required nested CSS Flexbox containers, which added a certain level of complexity. Both of the following solutions remove this Flexbox nesting.

Ilya Streltsyn: Use The CSS Property order

Ilya Streltsyn suggested moving the "dots" pseudo-element out of the DT and into the parent DIV container. This would make the pseudo-element the 3rd child of the Flexbox container which, by default, would render the "dots" at the end. But, by using the CSS property order, we can tell the browser to render the "dots" in between the DT and DD elements:

<!doctype html>
<html lang="en">
<head>
	<meta charset="utf-8" />

	<title>
		Revisiting: Styling A Movie Cast List Using A Definition List And Flexbox
	</title>

	<style type="text/css">

		a {
			color: red ;
		}
		
		dl.cast-list {
			font-family: monospace ;
			font-size: 20px ;
			width: 500px ;
		}

		dl.cast-list div {
			/*
				Setup the DT (character), DD (cast), and pseudo-element items as a
				flexible layout.
			*/
			display: flex ;
			margin: 5px 0px 5px 0px ;
		}

		dl.cast-list dt {
			/*
				Setup the DT (character) element to shrink, allowing for the dots to fill
				up the free space.
			*/
			flex: 0 1 auto ;
			margin: 0px 0px 0px 0px ;
			order: 1 ;
		}

		dl.cast-list div:after {
			border-bottom: 2px dotted #787878 ;
			content: "" ;
			/*
				Define the pseudo-element as a SIBLING to both the DT and DD elements.
				Configure it to grow, taking up all the free space with dots.
				--
				NOTE: We are using "order: 2" to place the ":after" element IN BEWTEEN
				the DT and DD elements, VISUALLY, even through it is PHYSICALLY the last
				child in the flex container.
			*/
			flex: 1 1 auto ;
			margin: 0px 12px 5px 12px ;
			order: 2 ;
		}

		dl.cast-list dd {
			/*
				Setup the DD (cast) element to shrink, allowing for the dots to fill up
				the free space.
			*/
			flex: 0 1 auto ;
			margin: 0px 0px 0px 0px ;
			order: 3 ;
		}

	</style>
</head>
<body>

	<h1>
		Revisiting: Styling A Movie Cast List Using A Definition List And Flexbox
	</h1>

	<h2>
		Using "order" &mdash; Thanks To Ilya Streltsyn
	</h2>

	<h3>
		<a href="https://www.imdb.com/title/tt0168987/">
			Better Than Chocolate
		</a>
	</h3>

	<dl class="cast-list">
		<div>
			<dt>Lila</dt>
			<dd>Wendy Crewson</dd>
		</div>
		<div>
			<dt>Maggie</dt>
			<dd>Karyn Dwyer</dd>
		</div>
		<div>
			<dt>Kim</dt>
			<dd>Christina Cox</dd>
		</div>
		<div>
			<dt>Frances</dt>
			<dd>Ann-Marie MacDonald</dd>
		</div>
		<div>
			<dt>Carla</dt>
			<dd>Marya Delver</dd>
		</div>
	</dl>

</body>
</html>

As you can see, we get the following three elements / pseudo-elements:

  • DT with order: 1
  • DD with order: 3
  • :after with order: 2

And while the :after pseudo-element is the 3rd and last child, its order gets the browser to render it visually as the 2nd child:

Moving the pseudo-element to the 2nd visual position using css order property.

As you can see, this works quite nicely. The other two sibling elements need to have an explicit order set. But, that's pretty trivial. Overall, I really like this approach.

Sime Vidas: Use The CSS Property display: contents

Sime Vidas' suggested leaving the pseudo-element where it is, but adding display: contents to the DT element in order to "unwrap" the term and the pseudo-element. display: contents essentially removes the container from the DOM, allowing the container contents to act as if they were siblings to their descendant elements.

<!doctype html>
<html lang="en">
<head>
	<meta charset="utf-8" />

	<title>
		Revisiting: Styling A Movie Cast List Using A Definition List And Flexbox
	</title>

	<style type="text/css">

		a {
			color: red ;
		}
		
		dl.cast-list {
			font-family: monospace ;
			font-size: 20px ;
			width: 500px ;
		}

		dl.cast-list div {
			/*
				Setup the DT (character), DD (cast), and pseudo-element items as a
				flexible layout.
			*/
			display: flex ;
			margin: 5px 0px 5px 0px ;
		}

		dl.cast-list dt {
			/*
				In order to avoid creating nested flexbox containers, we are going to use
				the "display: contents" to "remove" the DT element from visual rendering.
				This will promote the DT text and :after elements to be "siblings" of the
				DD element, allowing a single flexbox container to affect all 3 items.
			*/
			display: contents ;
		}

		dl.cast-list dt:after {
			border-bottom: 2px dotted #787878 ;
			content: "" ;
			/*
				Setup the :after element to grow, filling up the free space with dots.
				--
				NOTE: Since we are using "display: contents" on the parent container,
				this pseudo-element is logically rendered as a SIBLING of both the DT
				TEXT (implicit element) and the DD element.
			*/
			flex: 1 1 auto ;
			margin: 0px 12px 5px 12px ;
		}

		dl.cast-list dd {
			/*
				Setup the DD (cast) element to shrink, allowing for the dots to fill up
				the free space.
			*/
			flex: 0 1 auto ;
			margin: 0px 0px 0px 0px ;
		}

	</style>
</head>
<body>

	<h1>
		Revisiting: Styling A Movie Cast List Using A Definition List And Flexbox
	</h1>

	<h2>
		Using "display: contents" &mdash; Thanks To Sime Vidas
	</h2>

	<h3>
		<a href="https://www.imdb.com/title/tt0168987/">
			Better Than Chocolate
		</a>
	</h3>

	<dl class="cast-list">
		<div>
			<dt>Lila</dt>
			<dd>Wendy Crewson</dd>
		</div>
		<div>
			<dt>Maggie</dt>
			<dd>Karyn Dwyer</dd>
		</div>
		<div>
			<dt>Kim</dt>
			<dd>Christina Cox</dd>
		</div>
		<div>
			<dt>Frances</dt>
			<dd>Ann-Marie MacDonald</dd>
		</div>
		<div>
			<dt>Carla</dt>
			<dd>Marya Delver</dd>
		</div>
	</dl>

</body>
</html>

As you can see, in this case, we're using display: contents to "remove" the DT container from the DOM. This promotes the DT contents up one level in the DOM Tree, leaving us logically with:

  • (promoted element) Text (cast)
  • (promoted element) :after (dots)
  • DD
Logically removing the DT element from the DOM tree using display: contents in order to promote the nested elements to a higher layer of the DOM.

As you can see, when I try to select the DT element in the Chrome Dev Tools, no corresponding selection is made on the rendered page. This is because the DT has been logically removed, allowing the contents of the DT to move "up a layer" in the DOM Tree.

This is a pretty clever solution. But, I should caveat that display: contents doesn't have perfect browser support. According to caniuse.com, neither IE nor Edge support it currently. And, some of the browser that do support it have some bugs when it comes to these accessibility of these elements.

A huge Thanks to Ilya Streltsyn and Sime Vidas who looked at my code-kata and suggested thoughtful ways to simplify my solution! That's what's so great about being part of the wonderful Web Development community. Y'all are good people!



Reader Comments

@Chris,

According to caniuse.com, there is some accessibility bugs; but, I have heard that those may have been fixed in recent versions. I am not entirely sure. That said, that's why I prefer the use of order in Flexbox.

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
NEW: Some basic markdown formatting is now supported: bold, italic, blockquotes, lists, fenced code-blocks. Read more about markdown syntax »
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.