Functional Cascading Style Sheets

Introduction and Background

Craig Sharkie introduces the talk focusing on changing the approach to CSS in web development. He shares his background as a developer, advocate, author, and teacher, emphasizing the evolution of web development since the early days without CSS or JavaScript.

Early Days of Web Development and CSS

Discussion on the origins of web development, highlighting the limitations and simplicity of early web design, including the use of font elements for styling before the advent of CSS.

Functional Stylesheets and Semantic Web

Introduction to the concept of functional stylesheets and the importance of bringing semantics back to the web.

Reframing Simple Tasks

Craig explores the idea of reframing simple everyday tasks, such as eating bananas and folding T-shirts, to find more enjoyable and efficient methods.

Shoelace Tying Analogy

Using the example of different methods to tie shoelaces, Craig illustrates the idea of approaching tasks from new perspectives, drawing parallels to web development practices.

Applying Functional Programming Concepts to CSS

Discussion on how functional programming concepts can be applied to CSS, aiming to make stylesheets more functional, declarative, composable, testable, and immutable.

Testing CSS and Visual Regression

Exploration of testing CSS through methods like Selenium, Quixote, and visual regression testing, highlighting the importance of these practices in modern web development.

Leveraging CSS and Embracing New Techniques

Craig encourages leveraging new CSS features while also understanding traditional techniques, emphasizing the importance of both in effective web design.

Bundling Code and Functional Stylesheets

Discussion on the concept of bundling code in CSS, comparing it with JavaScript bundling techniques, and emphasizing the benefits of functional stylesheets in web development.

Conclusion: Joyful Development and Functional CSS

Conclusion stressing the need for a joyful approach to development and the potential of functional CSS to enhance collaboration and efficiency in web design and development.


So today what we're gonna be looking at is a way to change how we approach our CSS to make it part of a paradigm that you'll find when you're talking to some of the developers.

They will often, for some reason, think that, CSS developers aren't quite as, sophisticated, shall we say, as proper developers within quotes but we're gonna show them that we are gonna change that and we're gonna stand 'em on their head.

As Mark didn't say, I'm a developer, an advocate, an author, and a teacher, because when I started, there weren't any teachers.

There was like one author, and he's sitting over there with a stripy shirt on.

There were very few advocates, and there was just a bunch of developers not knowing what we were doing, because I started in about 95, when the web didn't have CSS or JavaScript.

It had HTML, and it was amazing.

but then I added in a presenter in there.

and on the back of that presenter, that's the way we started as a developer.

When I became a presenter, I had the opportunity to open up to become an author, and from the back of that, I became a teacher as well.

that's what's brought me here today.

I've been a part of the Web Directions family for a very long time.

I think that Mark and I need, at some point, to do an arm wrestle, and I think I'll get him.

we need to do it because you and I think, are running neck and neck for the most capped presenters at Web Directions Conferences.

stop it, or let me catch up again if I'm, if I'm behind.

I started when web directions looked a bit different, actually I'll go back even further, before web directions was web directions, and we were web essentials.

But that was a time wrapped in mist.

And it feels like it was last century, but it wasn't quite.

Just had different attitudes back then.

as I said, back when I started there was no CSS, let alone CSS3.

if you wanted to change the way that something looked on the web and it wasn't gonna be black text or a blue link, you would wrap it in a font element, and then you would add a color property to it.

And we thought that was just the best thing ever.

And then we now had three colors on our web page.

It was brilliant.

but don't worry.

functional style sheets aren't going to introduce any deprecated elements.

but what we should do is get some of the people who are doing functional programming to use more of the elements we've already got and get some semantics coming back to the web.

But we'll touch on that later, I hope.

In the course of those last 30 odd years, I've learned some things though.

some of them were about the web, some of them were less about the web, but we're going to touch on some of those first.

And we're going to do it with the help of our helpful guide, and he's going to take us through three steps as we keep going.

And you'll see as we start our first one, why the guide was so keen to help out, because it involved bananas.

In 2016, this man, Jeremy Keith, came to Australia, on the back of a Web Directions conference, and he did a thing called Web Jam, where we'd get together outside of the conference, and we'd just talk about whatever we wanted to talk about for five minutes, and we'd prove the world was a better place.

He asked the room full of people, do you eat a banana from this end?

And the room full of people said, of course we eat bananas from that end, what do you think we are?

He then pointed out to me in 2016, after I'd been eating bananas for almost 40 years, that primates don't do that.

If you're in the West, you eat a banana, you crack off the, handily applied natural handle on the end.

If you're a chimp, he was saying, or an ape, you'd eat through the soft end, which makes sense.

You don't want to eat the hard end first, you eat the soft end.

And he had visual proof to back it up, and we all thought he was great.

So for the last seven years, I've lived in an environment where I thought I ate bananas like a Westerner.

And there were people out there, and there were other animals on the planet who ate it differently.

In coming to research the slides for this presentation, I came upon a sad fact, though.

And that's the bananas don't live in the same places that monkeys do.

If you're gonna see a banana and a monkey together in the same place, there's a big chance that a human being has been involved in the process.

So what happens is that the human being naturally hands, the monkey, the banana monkeys take the banana and do what they do best, and they start, they eat it.

If you hand it to it in a different place, it doesn't care.

It just puts, the banana goes in the hole where the food goes.

Everything is great.

I'd lived in a world where I thought there was one way to eat a banana, mind was blown, there are actually many ways to eat bananas.

In a similar sort of sense, I'd learned about this process.

Now I can see people in the audience going, aha, I know what that is, that's the t shirt tool.

Exactly, see?

I thought that apart from getting your t shirts and jamming them in the back of the closet, you, there was only one way to really fold t shirts, you did the wrap around thing, and then the arm goes in and you fold it over and away you go.

Is that me?

Time is already up.

however, there seems to be a better way to do it.

There are people on the planet who are trying to come up with better solutions for doing nearly everything.

So I have here a cunningly placed T shirt that was from the first JSConf years ago.

that was our symbol for, automatic semicolon insertion.

Does anyone in the room know what automatic semicolon insert?


Okay, three of you.


and thank you, CoffeeScript.


When you go home, and you're about to fold your laundry as I'm sure you will really enjoy doing, don't just fold it up.

Place one hand cunningly near the top of the neck.

Place another one, between one third and halfway down to the t shirt.

Put your top hand over the middle hand, grasping the bottom.

Bring it out magically.

Fold it over, and you're done.

Now, I've just realized that with this microphone on and just doing this, I feel like I'm some sort of dumb sort of Demtel ad.

there's a simple way to fold it, which is just get it done.

There's a fun way to fold it, and I'm not going to say that I enjoy doing my washing, but I enjoy doing the folding when I get to the end of it.

A simple change to the way we're doing something allows us to get a little bit more joy out of what we're doing.

And there's our quick way.

And the last thing, For me, it wasn't an education point, it was a confirmation point, I'm glad to say.

And that confirmation point was that there's actually a way to hang toilet paper in the toilet.

It's not just a random act, there is a prescribed method, set about in 1891, when the patent for toilet paper was first proposed to the American Patent Office, and it's clearly pointing out that the paper has to go over the top.

Now, you might be having one of those really strange toilet setups where you've got a spike for the toilet roll and it comes out in some sort of chaotic either left or right process.

Doesn't matter.

It has to be over the top, otherwise it's wrong.

And I had to actually hold myself back when I walked through the gents before.

Because one out of three roles was the wrong way around.

And I think that someone in this building did that on purpose.

They were just trying to unsettle me.

But next time you see a large pile of toilet paper and you've got nothing else to do because when you see toilet paper you should Probably have nothing else to do.

Just think on that.

It's a pause, have a bit of a chance to think about the fact that toilet paper should go the one way that we all really know deep down in our heart of hearts.

Anyone disagree?

We still love you if you disagree, but we'll work on that later.

So we've learned those three simple examples.

That, even the simple things we do can be reframed slightly to allow us to come up with a more enjoyable way to approach them.

simple tasks can have simple alternatives and they can enrich the way we use them.

And what we're going to do now is try another thing.

We're going to add another thing to our learning process.

And that's going to be, through the medium of shoe, tying shoelaces.

Because I know, there's more than one way to tie shoes.

Did you know that there was more than, you knew there were, like, double laces and stuff, but did you know there was many more ways to tie shoelaces?

According to a man named, Ian Feigen, he reckons there's 25 ways to tie the shoelaces, and I thought, I knew there were two, because I had a, secret insider.

if you were born in the last century, this is how you would tie a shoelace.

You would take the left lace looking down, you would pass it over the right lace, back under, and through, and that would give you the basics of your knot.

Everyone does that, okay?

then, if you're born in the last century, you knew the rhyme, and that's that you make a tree, the rabbit runs around the tree until he sees the farmer, then he dives under the tree, and you just tie a little bow, and it's great.

That worked from the last century, and I didn't realize, until my daughter was tying her own shoes, that there was any need to change the way that people tied shoelaces.

She had one called bunny ears.

Starts out the same.

Left lace over the right, lace under back through, that's your basic knot.

And then you make rabbits ears, and then you wrap the rabbits ears together and then you pull the rabbits ears tight.

And I'm sure it's because little fingers with little bows make better knots if they do it this way.

But the end result is that you come out with a bow where the knot in the bottom and the knot in the top generally match up and away you go.

The result was, that was easy.


Start out with the process, you've got left lace, over right lace, you then choose between the two methods of how you want to tie your shoelaces.

Your left goes around your right goes underneath your left, and you've got a knot, that's fantastic.

Sounds good?


no, of course not.

because you're not wrong.

this is how you tie shoelaces.

Because it's, we thought it was a simple process, but it turns out that every simple process has a far more complicated underlying structure.

There's not just a knot and a double knot, there's a knot, a tulip knot, an ear knot, a snip knot, a freedom knot, and there's a whole bunch more knots, including that one in the top which is called a baluti knot.

Which looks like this, and in a balloony knot, you don't just go through once when you do your basic structure, you do it three times.

And you don't loop your loops once, you're looping twice.

And the reason for that is these guys aren't wearing trainers with nice gripping laces, they're wearing their posh Italian leather shoes with leather laces that slip apart.

So by going with the extra traction, you create a knot which you can trust better.

What we're going to do, though, is we're going to change the way we look at our knots.

And you can follow along if you like.

What I think you should do is don't take both shoes off at once.

Just do it with one foot, so you've got one as the control mechanism.

we're going to combine the two processes together.

We're going to do a change, a simple change to the way we tie our shoelaces, and we'll come out with a better knot in the end of the day.

And that's a leperine method.

We're keeping with our rabbit approach.

Previously, we started with our left lace over our right lace, underneath and through, and then we went.

In our approach now, though, when we do it, we're going to switch that around.

We're going to go, crazily, we're going to go left la sorry, right less over the left and back through.

The next step is whatever knot you choose, either the first method or the second.

And the result is the bow.

And it looks mostly like the bow we had before.

It should sit straight across your shoe.

Where if you did it a bit cack handedly, you might find that when you're little, you ended up with the shoelaces running strangely, or they just didn't quite hold together properly.

This method, because we're changing the way that the first lace runs, there's traction between the laces.

So a simple change to lacing is working means that we get a stronger lace, a stronger knot, that will stay together longer, and will keep our shoes tighter on our feet for longer.

And you didn't know you needed that.

But now when you go home and put your shoelaces on, you're gonna be thinking about the fact that, hang on, was he right?

Is there any sense to what he's talking about?

And eventually we'll start a subverted movement.

So I learned about, I thought there was only one way to tie shoelaces.

My daughter told me that there was another way to tie them when she was little.

And then on Tuesday, she said, dad, I'm now tie them like you do the old fashioned way.

So we're going to come up with a third, focus.

So we're going to have a third way to tie shoelaces.

And that's going to be this reverse granny not in the bottom, and then they're knot on top.

And we'll all get back home at the end of a hard day.

No, 'cause we're already at home.

At home when we go and wear our shoes out at some point, for some reason, at the end of the day, our shoes will still be tight.

They won't come undone.

We won't need to worry about double knots.

We've made a simple change to a simple process and we've got a better outcome.

And what we're gonna do.

is apply that sort of approach to our CSS, because we tend to do things because we do them.

we don't always review what we're doing, sometimes we don't need to.

There may be other ways to do it, and sometimes those small changes can yield with, yield better results.

In that line, how can we change our CSS?

How can we make very small changes to come up with a better approach to CSS?

Better in inverted commas.

the most simple way for us to do it is to not change anything.

Don't change your CSS, change the way you talk about your CSS.

And you'll find that people who are using the same language that you're, adopting will better understand your CSS processes.

We need to define first of all, our CSS.

And then we're going to do that.

We're going to say that functional is an adjective, it looks great when you write it with phonetic languages.

It's, practical and useful, it could be a special purpose, it might be able to work.

And there's a programming approach, which is that it's a programming paradigm where programs are constructed by applying and composing functions.

Underneath this approach of functional programming, you'll find that functions are treated as first class citizens.

They are declarative, they are composable, they are testable, and they are also immutable.

We can do all of our work with CSS without understanding any of these terms, but you will find that we can approach the way we, look at our CSS and make our CSS more like the approach from functional programming.

So what we're going to do is understand a bit more about functional programming, and then we'll come into that, into our CSS.

To do it, we're going to use JavaScript, which inherently isn't a functional language, but it can be written with a functional approach.

So what we're doing is the JavaScript developers have got a leave pass from the functional programmers to say that you're allowed to say that you're approaching your JavaScript functionally.

What I want to do is take on that same leave pass.

Get, allow the functional programmers to allow the JavaScript developers to allow us to say that we've got functional style sheets.

A first class, function is one that you can apply a function as a value to a variable.

Is anyone really deeply familiar with Functional Programming, or should be in the other room.

That's fine, we're here, we're all between friends.

those guys might know that a functional programming language is where the function can be applied as a variable.

We know we can do that, we've seen the, those guys do it.

We can also pass a function as a parameter into another function and it will work perfectly.

So here we're passing a function into the, setTimeout global function.

Everything works perfectly.

We can use ES6 syntax, it's all great, everyone thinks it's fantastic, but those two things together, excuse me, that process, we're elevating how we use functions so that we can parse them, we can rely on them as variables, and that gives us our first approach.

The next step is declarative, and declarative approach to our programming has a pair.

It's, declarative versus imperative.

If we were to say we need you to go somewhere, and we approach that direction declaratively, we just say, we want you to go to this place, get there by your own means.

We're declaring where we want you to go, we're not telling you how to do it.

If, however, We took an imperative method to it.

We want you to go to a place, but we're going to tell you exactly how to get there.

Don't go the longer route, go the shorter route, follow these steps, pass those points, take this time.

It's a lot more work to get the same output.

When it comes to our code, we don't necessarily care what the every method is doing on the array.

We are declaring that we want to know what's happening.

We want every element to be taken off the array and have something done to it.

But we don't care how you do it.

JavaScript, it's up to you.

We're gonna take a declarative approach.

If we don't be declarative, we're going down the imperative path.

It's a lot more work on our part.

So we've got, we have to do for-loops, we've gotta do conditionals.

We have to make sure that we are doing the right syntax and we've got the right sort of steps going through that.

We're setting the i variable at the right point in time, and we're doing our returns in the right place.

It's easier for us if we take the declarative approach.

Get the simple outcome, and as Lachlan said, you can just get that done and focus on enjoying the code that you're writing instead.

A composable piece of JavaScript, and that is in our next step, here is an example from jQuery.

Now I would have thought when I wrote my book on jQuery that I wouldn't be standing on a stage now wondering if most of the audience has ever written jQuery.

And I don't even think next door has written jQuery.

But the approach is that we pass a selector, a CSS selector into jQuery.

It went through the DOM, grabbed us a, a collection of elements that matched that selector, and then moved them down the chain of functions that were all joined together by those dots.

In the first step, it adds a style parameter to our element.

And the next one will add a class element, a class parameter to it.

So it's changing the style of way through.

We're composing our methods together to come up with a final outcome.

next of all is testable.

we'd love testing code.

I, I do, except when it's written like this, which is written like the way the guy text talks.

everyone's seen these nasty, functions.

It's deeply nested.

There's heaps of different scopes going on.

The lines are really long and hard to read, and even worse than that.

It's incredibly long.

And that's just one method that you can't ever hope to test that sort of code, but changing the way we write our code to be more functional, we reduce the amount of scope we've got inside a method and we increase the number of functions that we've got.

So here, the first two, if conditions don't actually relate to the outcome of our intention with the function, which is to add numbers together.

They just make sure that the things we've got are numbers.

So we can move those, pieces of code out to their own function.

We'll have an isNumber function addNumber function, we'll call that.

We've now got two discrete methods where if we were going to do, our next function was to do subtract, we wouldn't need to add another piece of inline code.

We can use the isNumber function that already exists.

So we've got small pieces of code, which are easy to understand.

And actually we can make the bottom one even easier to understand by chain taking out, variables that are no longer as required because our now our code being more succinct is a lot easier for us to read.

And that's what we talk about when we're talking about testable code.

We've got two small functions, easy to, approach, and our test might look like this.

Really straightforward is 2 a number?

is the sum of two and two gonna be four?

And we, give the tests, the values that we expect, and we have the outcome come through.

We've got testable code.

We can finish work at five o'clock in the evening on Friday and know that as long as the process is done and our continuous integration, process has running our, is running our tests.

We're not gonna get a call until Monday morning, so that should be good.

We've got a weekend where we can put our feet up.

Immutability, immutability is very hard to do in CSS will come to see, but in, in JavaScript, it's now quite straightforward.

Everyone has a variable, is a variable, is a piece of, construct, which we can give a value of value to.

We can then go through later and change that variable to whatever we chose to do, that's mutable code, it's code that can change.

We've got our increase now, we've now got the let variable as well as the, a variable, a parent variable.

Let will allow us to do the same thing in scope.

It's a little bit easier to read, but you can still find cases where the value that you expected when you read the beginning of the code has changed by the end of the code that you're reading it with.

However, if we go with a constant, we've now got immutable code.

We know that when soon as we read that variable into our code, when we want to go and use it, It's going to be exactly the same.

It means that there's a lot less chance of collisions.

A lot less chaos going on.

If we do try and change it, we're going to get a quick error in our console.

We've all seen those, but it's just a nice way for the code to come back and let us know what's going on.

And I hid the water, but I don't think I've got it.

I think it's fine.

We've proved, though, that functions are, can be treated as first class citizens of JavaScript.

they're declarative, they can be composable, they're testable, and the, assignments can be immutable.

All those things together allow JavaScript to claim to be a functional language.

Functional stylesheets, then, need to take those five approaches and show how, without doing too much to the language itself, we can actually come up with a process that will allow us to claim the status of functional stylesheets.

We need our functions to be treated as first class citizens.

We need to make sure that our statements are declarative, that our selectors are composable, our styles are testable, and our styles are immutable.

Now, most of those we can nail straight out of the box, we'll see in a second.

The last one will come down to convention.

First class, methods in JavaScript, we've got functions, sorry, in CSS, we've got functions in CSS.

We've had them for a very long time.

here we've got a, calc function, which is accepting a variable function.

Here's our calc, accepting the variable.

We've nailed first requirement that we can pass a function through to another function and utilize it.

We've now got first class functions in our CSS.

The declarative nature of CSS is even more fundamental.

we can look at setting a class, setting a color on an element by using a hex string.

we can use an RGB, we can use HSL, we can even use a color name for it.

What we can't dictate is how the user's going to see it.

They might have assistive technology, they might have an environment which doesn't allow for a great deal of light to come through.

There may be some reason why they need to dim the, the output from their screen.

We can declare that we want the color of that component to be goldenrod.

But we can't ensure that it's going to be, we don't implicitly tell the device how to render the color, we just say we want you, our best approach is for us to declare that it'll be goldenrod and you can do the best thing for us, but our screens can come up with any sort of environment at all, on the, positive side, we do have a declarative approach to our CSS.

Composable CSS, here we've got a ridiculously long selector, until about an hour ago, I thought that there were, three different processes, three different steps to it, but I realized that there was the asterisk there, so there was actually four different, components in this selector that pass information about the components that we're looking at back up the selector in reverse order.

So it starts with four and it says, are you any type of element whatsoever?

And all the elements go, yeah.

And then it says, are you a list item?

That is an odd list item.

Are you the list item of an unordered list that is the last child of its parent?

And is that parent the third div in its parent itself?

So if we are composing using our selector, our approach to getting the elements we want to apply our styles to.

So yes, we have got composable, composables, the nature in our CSS.

And again, we can take on board the process from Tailwind, which removes the need for us to compose, classes themselves, coming up with small classes that match small elements of CSS.

And then we combine them together into our class names, which gives us another way to look at our CSS as being composable.

And of course we can have testable CSS.

And, it's not common to find, but it's heaps of fun to do.

You can use something like Selenium, which will give you a headless way to look at your, your web application.

And you can, step through the interface the same way that a user would, even though you're headless.

You can poll the units using a system which roughly gives you the same output as your developer tools.

And you can find out what a style, like what an element thinks it should have, what its color is, its background image, and all those sorts of processes.

So it's possible to actually test it.

If you find that the expectation doesn't match reality, the test will fail and away you go.

Similarly, you can use a process like, Quixote, which will give you a framework where you put your code inside the Quixote framework, and it will give you a chance to write tests like you might have seen if you were writing them in normal JavaScript.

And lastly, the more fun thing with, with CSS, which is the hardest one to nail, is visual regressions.

Rather than worrying about code, you take snapshots of sites, and allow, you're then allowed to go back and compare those two together using the processes.

If the tests pass, they come back green.

If there's been a change to the interface, then it comes back as a problem.

Now, it's not, I always hated calling them failures because it might not be a fail, it might just be a change to the way you're wanting it to run.

you may have thought that that having that X across on the right hand side was too far across.

So you want to move across to the middle.

If that's now where you think it should be, you accept that as the passing test.

It gets stored as a reference point.

And the next time you run your test, you can do a visual regression against them to make sure that there's been no changes you didn't expect.

And lastly, on that front of the, of testing, cause it's, it can be a really useful tool is of course, you might work with a platform that allows you straight out of the box to have visual regression testing without having to do any extra work.

And we bring ourselves to immutable.

You might know, that we didn't used to have constants in JavaScript.

And we had a convention that we would write a constant, we'd write a variable name in uppercase.

And by contracting with our other developers, we would say, if you see a variable with an uppercase name, don't change it.

It's what it's supposed to be.

We're going to take on a similar approach in CSS.

if we were to have immutable code, sorry, mutable code in CSS, We'll take an obvious thing.

So we've got a goldenrod color still being applied to a div with a class of golden.

That makes sense.

If we suddenly just inject a random, let's change the color of that component to red, it's very difficult for someone to track down where we're doing it.

I know we can use that, developer tools to do it, but if you're not a CSS developer, just being able to randomly inject things into your code is not seen as a very positive way to approach the whole process.

So what we need to do is by convention don't just have one class with everything going on in it, break your classes down into smaller bits that become almost self documenting and we'll have a golden copy and our copy goes in there.

It's still a bit of a clash that it's, called golden, but it comes out red, but.

That's the way that Tailwind likes to do it.

We're okay, we'll just keep moving forward.

on the back of that, we've seen that we can actually have functionally functional CSS, and we should be able to bring joy to our developers, except we don't.

mostly the developers will still be, at least to some extent, a bit cranky.

So we want to come up with some functional practices they also approach, and we'll do those in conjunction with our functional style sheets.

And see if we can come up with a way to make them at least a little bit less cranky.

and again, we've got our guide helping us out.

today though, we're only going to look at two different ways in this process to work.

The first of them will be leveraging CSS.

Now, the last two presenters both said there is new ways to approach CSS.

Don't let them lie fallow.

Embrace them.

Erin's and Erin's, it was on both sides.

She was saying, leverage new CSS because it's fantastic, but also understand old CSS because it was just as fantastic.

and we need to do that.

We need to look at the fact that, yes, there's been a bunch of new things released.

So we've got our container queries that we looked at, with Trung's presentation.

But we've got the :has selector and we've got 20 different things that have been released this year in CSS alone, that can give us a greater way to influence the code that we're working with.

Now that the, developers in the other room have got 20 and a bit, like 21 maybe, because they had to beat us.

They've got 21 features that have come out in JavaScript, but we'll let them have that and we'll just take this approach.

But if we embrace what we've got, the tools we've got with CSS, it means that we're not relying on other people in the team to do our job for us.

We know what we're doing, we can make fast changes, we can make quick changes, and we can impress not only ourselves, but also our users as well, hopefully.

And as I was saying, and Erin pointed out, there are older techniques we don't always necessarily pursue properly.

we H1 on our page which tells us all about CSS.

We might think that it's going to make it look a little bit more compelling.

And we know that CSS loves working with gradients.

So how do we get CSS on to text as a gradient?

And it's ridiculously straightforward.

We don't need to go to the design team and say, look, we've got a new heading coming out.

Can you make us a bespoke heading with a special style applied to it?

We don't need to go to the developer and say, we need to do a special release to make sure we've got this heading before the application goes out.

We just use some lovely gradients and some lovely CSS.

And again, we've got a linear gradient function up here.

So we're relying again on our functional.

approach to CSS, a background-clip text and our webkit-background, because even though the, can I use is coming out saying that the background-clip text is fully supported across all the browsers, it's fully supported across WebKit browsers, as long as you use the vendor prefix, which kind of isn't full support, but they'll get there one day and it'll be fine, we can, drop it off.

and you get this, the beauty of this, obviously you can get whatever style you want to apply to a, to, we can apply to a background, you can apply it to now to text as well.

And because it's working off the background properties, our guide can come along and he can join in.

You can make it more compelling for a certain group of people.

You can set a tone more with your CSS because everyone's sitting here with their winter woolies on and not worrying about the sun and the beautiful sky.

But we do that just by simply changing it and using an image in our backgrounds.

We can make the CSS smaller, we can make me part of the focus, and we can do everything like this because we know that CSS is awesome.

It's still awesome.

The next thing we're gonna look at though is bundling code, and this is the big one.

This is the thing that actually started me off in this, on the road to trying to understand if we could become functional stylesheet programmers, is bundling code.

The big problem we had with CSS is that we can include it externally.

We can look at it coming from, In the document, we can look at it inline.

We can have it coming in through, JavaScript.

And I think it was really interesting what Erin was saying about the fact that, a block level element isn't actually anything clever.

It's just an element with some CSS applied to it in the background.

we need to keep this really quiet, but whenever JavaScript works with, making style changes, it's not doing JavaScript.

It's talking to CSS.

JavaScript can't make the style change.

JavaScript just hooks into the CSS engine that we're currently using ourselves.

So for us to be able to elevate our CSS back up to being a first class citizen, spot on.

But we've got this, we're playing a JavaScript style here.

We can do it and we've got our module approach and we've got, style components.

We haven't got any of your put, no, but we could.

We can.

It's great.

But we've, if we approach the problem we've got, because if we don't look at changing the way we write CSS, we end up with ridiculously long stylesheets that have code that we can't read, that two different developers will look at two different places in the code and not see what they need and add another version of the same piece of code that already existed.

So someone will come and delete one piece of code and then they find that when we're sure we've deleted it, it's actually still showing up in one of the most important parts of the site.

And that's because our stylesheets are difficult to maintain.

But what we can do We'll split them down, but that requires a human being to go through and keep continually manipulating those smaller style sheets, which is better, but still not good enough.

There's a better way, and that's through bundling.

And it's the process that the developers use when they're writing their JavaScript.

they put components into a component directory.

They write small pieces of JavaScript.

They run a bundling process over the top of it.

It joins them all together into a single, single piece of script.

Then you post it up onto the web.

And we can do the same process.

With our CSS.

So we import the style sheet so that Webpack can utilize it.

We then use CSS loader or style loader in combination, and we put them into the config and we then started to use exactly the same process, as I said, that the developers are using for their JavaScript and we're doing it in our, with our styles, we can output CSS.

We can, using the same process as you can see, we can include and exclude.

different, files in different, in, in, the tree structure.

So CSS modules can actually still work in conjunction with our approach to just making a concatenated style sheet.

We can run processing over the top of it, which will remove duplication.

So our style sheets become smaller.

All of them, there's all those evils that we were seeing that were being solved with CSS and JS can be counteracted by using a bundling process to get a natural approach to using CSS back.

up into the forefront.

So here we see that, we've got a small button CSS, which is sitting next to the button.

js file.

So the developers know where the code is.

If we decide to ditch the button component, when it goes, we we won't reprocess our file.

We don't have any legacy styles hanging around.

The developers are happy.

They've got smaller files.

The, the bandwidth is, being reduced.

We're using, we're adopting processes that the developers are using.

So we get kudos there.

And it's starting to become a process of becoming full circle.

So when I started, there was CSS and we added some HTML, we added some CSS to it.

Then we added some JavaScript and some people thought, like myself, that we went too far the wrong way and we did everything with JavaScript, but now we're starting to see that.

They're coming back.

And one of the things you'll, you'll start hearing about is things like critical CSS, where we're using processing because we've now got our bundle process with our CSS, we can utilize, Webpack there, and we can take a small piece of code out that just runs everything we need to load the, a web page above the fold, and our time to, critical content is reduced greatly.

So we should be able to, better engage our CSS, our, audience, sorry.

Do we have then, after all that, with all of our five processes and our two different practices, do we have a joyful, developer in our team?

possibly, because I think that what we need to start acknowledging is that not that CSS was a problem, but the JavaScript developers had other problems that allowed us, it washed over us as well.

they might've worked with, Webpack.

They could have used Vite instead, they might have also had to have used Grunt, or sorry, Gulp or Grunt.

That was all laid over with them needing to use Node, or Audino, and JavaScript by itself, and they're using, composable JavaScript or, ESM files, all these different processes.

It means that any disgruntled JavaScript developers probably weren't, really hating on CSS, or just taking it out on us because we were something more of an easier target.

We haven't yet come to a point where the developers are going to be completely without rage, but hopefully we can diminish that rage to an extent.

Joy, we're hoping that we're there.

I think we did it to an extent.

We've reframed our CSS, which means we can now discuss that CSS with our functional programming buddies.

And we've now got, I think, an approach towards functional stylesheets.

That's where functions are treated as first class citizens.

Our statements are declarative, our selectives are composable, our styles are testable, and our styles are immutable.

And thank you.





Web Directions

Old web directions logo
Web Essentials 04 logo.
The image displays the CSS3 logo, which is covered by a red prohibition sign
<font>Hello, world!</font>
<font color="red">Hello, world!</font>
Shows the MDN page for the font element.


The image contains a close-up of a chimpanzee with a neutral background. The chimp's mouth is wide open, showcasing its teeth, and it appears to be looking directly at the camera.
A chimpanzee's face is centered in the image, appearing to look directly at the camera. Beside the chimpanzee's head to the left, a speech bubble with the number "1" is present, indicating the start of a sequence or list. In the background, the numbers "2" and "3" are faintly visible, suggesting continuation.
A single ripe banana with a vibrant yellow color displayed against a clean, white background.

Portrait of Jeremy Keith

A photograph of a single, ripe banana on a white background. To the right of the banana is a blue circle with a white outline, concentric to the circle, highlighting the stem end of the banana. A thick blue arrow points from the banana to the circle, indicating the focus on the stem area.
A photo of a single ripe banana on a white background. The banana is positioned diagonally, with the stem on the right and the tip on the left. There is a large blue circle outlined in the center of the image, highlighting an area of the banana near the tip. A blue arrow points to the circled area, drawing attention to it.
A monkey with golden-brown fur is holding and eating a banana against a clear blue sky background. It eats from the rounded end.
The image displays a single, ripe banana on a white background. Two circular blue outlines highlight specific parts of the banana: one circle is around the bottom tip of the banana, and the other is around the stem area. Blue arrows point towards these circles, suggesting a focus on these parts of the banana.
A graphic image depicting a banana partially obscured by a series of overlapping blue circles.
The image contains a close-up of a chimpanzee's face looking directly at the camera. Above the chimpanzee's head is a speech bubble graphic with the numerals "1", "2", and "3" arranged horizontally within the bubble. "2" is highlighted
A device for folding t shirts.
The image contains a series of numbered steps with accompanying illustrations demonstrating "WAYS TO FOLD A T-SHIRT" under the title "THE BASIC FOLD". Each step includes a visual representation of the folding action required: a T-shirt face down (Step 1), folding in the sleeves (Step 2), folding the shirt bottom to top (Step 3), and a final fold in half (Step 4).
A headshot of a chimpanzee facing forward with a neutral expression. To the top left, large faded numbers "1 2" can be seen, and to the right of the chimpanzee's head, a prominent blue speech bubble with the number "3" is displayed.
A single roll of white toilet paper with a visibly loose end, centered against a white background. The roll is intact with no signs of usage, and the design features small embossed patterns.
A technical drawing on a blueprint background with two different views of toilet paper.
A photograph of a pyramid of white toilet paper rolls with a quilted pattern. Multiple rolls are stacked in layers, with each subsequent layer having fewer rolls, forming a pyramid shape.
The image shows a toilet paper roll holder with a translucent faceted knob on one end, set against a bright background. The holder and its fixtures are metallic, and the design appears to be of a classic, elegant style. A partially unrolled toilet paper roll is mounted on the holder, giving a sense of its intended use in a bathroom setting.




A pair of brown leather dress shoes with blue laces neatly tied and sitting side by side. The shoes are positioned against a contrasting background, and they feature brogue detailing on the toe caps. The photograph emphasizes the new and pristine condition of the shoes, showcasing their polished surface and fine craftsmanship.


Website for Ian's Shoelace site.


bunny rabbit

The image illustrates a simplistic diagram of an overhand knot tying technique using two ropes of different colors. A yellow rope and a blue rope are intertwined in such a way that the ends of each rope loop around and pass through a common central loop formed by the two ropes. The image is on a plain white background with a copyright statement and a website URL at the bottom: © Ian W. Fieggen
A sequence of four images showing the steps to tie a knot with two ropes. Each subsequent image illustrates the progressive action required to form the knot, starting with a simple loop and ending with a completed knot.


bunny ears

The image is a simple illustration of two shoelaces interlaced in a way that forms a knot. There are three visible segments: one yellow, one blue, and another yellow. Each segment loops around the others, creating an interlocked pattern.


The image contains a diagram showing the steps to tie what seems to be a reef knot. There are four main steps: Step 1 with text instruction, Step 2 with two points listed, Step 3 with another single text instruction, and the final Result which simply shows the word "REEF" twice indicating the completed knot

Since the image only contains the word "RIGHT?" in blue text, there is no OCR required for transcribing text as it's simply a single word. However, I will provide you with the structured HTML content.



A very co,plex set of instructions for tying a shoelace.


Types of Knots

  • KNOT









Two hands tying a shoelace on a brown leather shoe. The individual is making a knot, with one hand holding a loop and the other pulling the lace through to tighten it.
The diagram depicts a circular flow with six steps involving four pointed shapes that resemble stylized arrows.
The image displays an artistically drawn depiction of a shoelace knot, consisting of three loops in blue, yellow, and black colors interlaced with each other.


A diagram of a blue and yellow shoelace tied in a knot on a white background.

Key Points


HOW CAN WE change CSS?


Excerpt from photo of a page in a dictionary.

functional adjective


  1. practical and useful; with little or no decoration
  2. having a special purpose
  3. working; able to work
  4. PROGRAMMING a programming paradigm where programs are constructed by applying and composing functions.












const logNumber = function (val) {
  if (typeof val === 'number' && !isNaN(val)) {
    console.log(val + " is a Number");
function logNumber(val) {
  if (typeof val === 'number' && !isNaN(val)) {
    console.log(val + " is a Number");

let val = 42;

setTimeout(function() { logNumber(val); }, 2000);


function logNumber(val) {
  if (typeof val === 'number' && !isNaN(val)) {
    console.log(val + " is a Number");

let val = 42;

setTimeout(() => logNumber(val), 2000);




Digital map showing walking instructions

function arrayOfNumbers (arr) {
    arr.every(el => isNumber(el));
function arrayOfNumbers (arr) {
    for (let i = 0; i < arr.length; i += 1) {
        if (typeof arr[i] !== 'number' && isNaN(arr[i])) {
            return false;
    return true;
function arrayOfNumbers (arr) {
  arr.every(el => isNumber(el));
There is no transcribable text in this image apart from the single word "COMPOSABLE." However, given your instructions not to provide an tag or the HTML structure, I'll proceed to present the word in the structured HTML format as requested.


$("div.confused").css("color", "red").addClass("blue");
  .css("color", "red")


A large block of code–details can't be seen

function add (num1, num2) {
  let number1, number2;

  if (typeof num1 === 'number' && !isNaN(num1)) {
    number1 = num1;

  if (typeof num2 === 'number' && !isNaN(num2)) {
    number2 = num2;

  if (number1 && number2) {
    return number1 + number2;

function isNumber (val) {
    if (typeof val === 'number' && !isNaN(val)) {
        return val;

function add (num1, num2) {
    let number1 = isNumber(num1);
    let number2 = isNumber(num2);

    if (number1 && number2) {
        return number1 + number2;
function isNumber (val) {
    if (typeof val === 'number' && !isNaN(val)) {
        return val;

function add (num1, num2) {
    if (isNumber(num1) && isNumber(num2)) {
        return num1 + num2;
test('2 is a number', () => {

  test('Sum 2 and 2 is 4', () => {
    expect(add(2, 2)).toBe(4);


var variable = "Hello, World!";
variable = "Hello, CODE!"; // value updated
const variable = "Hello, World!";
variable = "Hello, CODE!"; // TypeError thrown
Browser console shows error thrown






div {
  width: calc(var(--variable-width) + 20px);


div {
  background-color: #DAA520;
div {
  background-color: hsl(42.9, 74.4%, 49%);

div {
  background-color: GoldenRod;
The image shows a collection of six vintage mobile phones from the late 1990s to early 2000s era, arranged against a vibrant yellow background.


div:nth-of-type(3) ul:last-child
li:nth-of-type(odd) * { font-weight: bold; }
Homepage for tailwind CSS.


Homepage for Selenium
Github page for Quixote.
// 'frame' is the Quixote test frame.
const header = frame.get("#header");
const navbar = frame.get(".navbar");;
Visual diffing test results

Screenshot of visual regression test page


div.golden {
  background-color: GoldenRod;
div.golden {
  background-color: GoldenRod;
  color: Red;
div.golden {
  background-color: GoldenRod;

div.golden-copy {
  color: Red;


The image features a woman with curly hair, smiling as she looks at a laptop she is holding with both hands. The background is solid yellow, evoking a cheerful and vibrant mood.
A man expresses frustration or anger towards an open laptop. He is leaning forward and shouting at the screen, appearing highly emotional. The background of the image is white, bringing full focus to the man and the laptop.


A photograph of a chimpanzee facing the camera with an open mouth, showing its teeth in a possible smile or grimace.
The image shows the upper part of a chimpanzee facing forward, with a neutral expression. Above the chimpanzee's head are two speech bubbles. The left bubble contains the number "1," and the right bubble, which is only partially visible, contains the number "2."


What's new in CSS and UI: I/O 2023 Edition

Screenshot of article at

  • Container queries
  • Style queries
  • :has() selector
  • nth-of microsyntax
  • text-wrap: balance
  • initial-letter
  • Dynamic viewport units
  • Wide-gamut color spaces
  • color-mix()
  • Nesting
  • Cascade layers
  • Scoped styles
  • Trigonometric functions
  • Individual transform properties
  • popover



The image displays the acronym 'CSS' in large, white, bold letters centered on a black background.
This is an image displaying the acronym "CSS" in large, bold, red letters on a black background.
:root {
    --gradient: linear-gradient(#ff8a00, #e52e71);

h1 {
    background-image: var(--gradient);
    background-size: cover;
    background-clip: text;
    -webkit-background-clip: text;
    color: transparent;
The image features the acronym "CSS" in a large, bold font, filled with a gradient that transitions from pink to red to orange hues. The background is solid black, creating a striking contrast and highlighting the vibrant color of the gradient in the lettering.
The image contains the text 'CSS' in large white letters. The letters themselves are cutouts, revealing the face of a chimpanzee behind them. The 'C' and 'S' on the left show the eyes and face, while the 'S' on the right shows the mouth and teeth of the chimpanzee.
The image shows the acronym "CSS" in large, bold letters. The letters are filled with a photographic image of palm trees and a blue sky, creating a visual effect where the texture and scenery are shown within the shape of the letters against a dark background.
:root {
  --mascot: url(/media/DFYTxlbx0AA7dDU?);

h1 {
  background-image: var(--mascot);
  background-size: cover;
  background-clip: text;
  -webkit-background-clip: text
  color: transparent;
The image shows the letters "CSS" in bold white font, spanning across the image horizontally. In the negative space within and around the letters, there is a close-up photograph of a chimpanzee's face. The chimpanzee's eyes align with the top curves of the letters 'C' and 'S' on the left, while its mouth is agape showcasing teeth, which aligns with the bottom curve of the 'S' on the right side. The image is set against a solid black background.
The image features the letters "CSS" in a large, bold typeface, with the letters filled with an earlier image of Craig.


<link rel="stylesheet" id="wp-block-library-css" href="" type="text/css" media="all">gt; <style id="global-styles-inline-css" type="text/css">gt; body{ --wp--preset--color--luminous-vivid-orange: #ff6900; --wp--preset--color--luminous-vivid-amber: #fcb900; --wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(255,184,0,1) 0%,rgba(255,105,0,1) 100%); } </style>gt;
document.getElementById("p2").style.color = "blue";

Is that CSS?

Chimpanzee asks "is that CSS?"
document.getElementById("p2").style.color = "blue";
There are no images, diagrams, tables, or graphs in the image that require a description.
import styled from 'styled-components';

// Create a component that renders a <p> element with blue text
const BlueText = styled.p`
  color: blue;

<BlueText>My blue text</BlueText>
a huge wall of tiny concatenated CSS.
over a dozen links to style sheets


Webpack logo
import React from 'react';
import ReactDOM from 'react-dom';
import App from './components/App.js';
import './styles.css'; // <-- import the css file here, so webpack will handle it when bundling

ReactDOM.render(<App />, document.getElementById('app'));
Github page for css-loader
Github page for style-loader
module.exports = {
  entry: './src/index.js',
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'bundle.js',
  module: {
    rules: [
        test: /.js$/,
        exclude: /node_modules/,
        use: { loader: 'babel-loader' },
        test: /.css$/,
        use: ['style-loader', 'css-loader'],
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
module.exports = {
    module: {
      rules: [
          test: /.css$/,
          use: [
              loader: "css-loader",
              options: {
                importLoaders: 1,
                modules: true,
          include: /.module.css$/,
          test: /.css$/,
          use: ["style-loader", "css-loader"],
          exclude: /.module.css$/,
Project outline shows button.css and Button.js in the same folder.


The CSS, HTML and JS logos appear to coincide with them being mentioned.
A smiling woman with curly hair, wearing a white shirt, is holding a laptop with both hands and looking at the screen. She appears to be engaged and positive about what she sees on the display. The background is a solid, bright yellow color.



A man in a dark-colored shirt appears very frustrated or angry with his laptop. He is leaning forward with his mouth wide open as if yelling at the screen.






The image features a chimpanzee with its mouth open wide as if it was smiling or laughing. Above the chimpanzee, there is a stylized speech bubble containing the words "THANK YOU" in bold, capital letters.