Building a Computer with CSS

Introduction to Amit Sheen's CSS Talk

The host introduces Amit Sheen, highlighting his previous work with creative CSS animations and keyframes. Amit is known for his innovative CSS demos, and today he aims to showcase something even more impressive by attempting to build a CPU using CSS. The introduction sets the stage for a talk that promises to challenge perceptions of CSS's capabilities.

The Genesis of a CSS CPU

Amit Sheen shares the backstory of his ambitious project to build a CPU with CSS, which began as a challenge during a casual conversation with fellow developers. He humorously recounts how a debate over whether CSS is a programming language led to a dare that sparked his creative journey. This segment provides context for the talk and sets up the exploration of CSS's potential.

Understanding CPUs and Logic Gates

Amit explains the fundamental concepts of CPUs and their reliance on logic gates, which are the building blocks of digital devices. He introduces the basic types of logic gates such as NOT, AND, and OR, and their roles in computation. This foundational knowledge is crucial for understanding how a CPU can be simulated using CSS.

Building Logic Gates with CSS

Amit begins the demonstration of constructing logic gates using CSS. He walks through creating a NOT gate, explaining how inputs and outputs are represented using checkboxes and CSS properties. This segment illustrates the practical application of CSS in simulating basic computational logic.

Expanding to AND and OR Gates

Continuing the demonstration, Amit constructs AND and OR gates using CSS. He explains the logic behind these gates and how CSS selectors can be used to simulate their behavior. The segment showcases the versatility of CSS in handling more complex logical operations.

Completing the Set of Logic Gates

Amit completes the set of logic gates by adding NAND, NOR, XOR, and XNOR gates. He discusses the unique properties of each gate and demonstrates how CSS can be used to implement their logic. This comprehensive overview of logic gates lays the groundwork for more complex computations.

Binary Numbers and Basic Addition

Amit introduces binary numbers and their significance in digital computation. He explains how binary addition works and sets the stage for implementing addition using CSS logic gates. This segment is essential for understanding how basic arithmetic can be performed with CSS.

Building a Half Adder with CSS

Amit demonstrates the creation of a half adder using CSS, which can add two single-digit binary numbers. He explains the role of XOR and AND gates in this process and shows how CSS can simulate these operations. This segment highlights the practical application of CSS in performing basic arithmetic.

From Half Adder to Full Adder

Building on the half adder, Amit explains the concept of a full adder, which can add two multi-digit binary numbers. He describes how multiple half adders are combined to handle carries and sums across digits. This segment demonstrates the scalability of CSS-based computation.

Implementing a Full Adder with CSS

Amit showcases the implementation of a full adder using CSS, detailing the logic and CSS properties involved. He explains the use of custom properties to manage intermediate values and demonstrates the full adder in action. This segment illustrates the complexity and potential of CSS in simulating digital circuits.

Conclusion: The Power of CSS

Amit concludes by reflecting on the initial question of whether CSS is a programming language and affirms its capabilities by demonstrating a CSS-based CPU. He emphasizes the creative potential of CSS and encourages the audience to explore its possibilities. This segment wraps up the talk with a call to action for CSS enthusiasts.

Q&A: Exploring CSS and Logic

During the Q&A session, Amit addresses questions about the feasibility of building a CPU with CSS, the use of selectors, and potential optimizations. He discusses the theoretical completeness of CSS and shares insights into his creative process. This interactive segment provides additional depth and context to the talk.

Showcasing Additional CSS Demos

Amit shares some of his other CSS demos, including optical illusions and interactive animations. He explains the mathematical concepts behind these creations and how CSS can be used to achieve complex visual effects. This segment highlights the artistic and technical versatility of CSS.

Bramus: Amit Sheen. He spoke at CSS Day before. I think it was 2022 and Amit showed some very nice and cool animations, got very creative with keyframes. I was really mind blown by all this.

Speaking of being mind blown, if you've seen any of those crazy CSS demos out there that rely heavily on calculations, half of them were probably built by Anna Tudor and the other half were built by Amit. He is going to blow us away. And today he's going to blow us even more than he typically already does because he's going to build a CPU with CSS.

So yeah, next time complains - somebody complains to you about CSS being hopelless, like "I can't properly vertically align the thing", show them the thing that Amit is about to show. So please give him a warm hand. Amit Sheen.

AS: Thank you, thank you, thank you all. Yeah, it's great being here again.

CSS Day back on stage, just like Bramus said, last time I was here talking about animations and key frames and I really tried to do to give real value to the audience. Today we are going to build a CPU. So that means welcome to the least practical talk of this conference.

But I hope that through this talk you are actually going to learn just maybe a little bit CSS and a little bit how actually CPUs work.

So before we are going to get started, I am going to take you through a little backstory of how we even got here.

This whole concept started for me about just over a year ago.

I was at a meetup - after a meetup - we were sitting in a bar, a couple of developers talking about front end and I just noticed that they all have beards. I don't know why. Let's say for the sake of argument that this guy is me, okay? Now during this conversation, I don't know how it came up, but one of the developers said - asked the silly, silly question, "is CSS a programming language?" Now, I'm not going to get into this question. I really hope that everybody in this room knows the answer is yes. But back then in the bar I had to defend CSS. So I said, "yeah, of course it is." And I didn't stop there because maybe I was a few beers in. So I said, "I can build a computer with pure CSS." Now, to be honest, when I said it, I had no idea how to actually build a computer with CSS. I didn't even know if it was possible. But it didn't really matter because the other developer said, "no, you can't", and if you know anything about me, then I hate this sentence. Nobody tells me that I can't do anything. So I immediately answered, "yes, I can." And I thought that this would be the end of the story. But then he said, "I dare you." So here we are.

So now we're going to build a CPU. And to build a CPU, let's start by understanding what a CPU is.

So I'm guessing most of you, maybe all of you, has a CPU on you. It's in your laptops, in your phones, in your smartwatches, in your vape pens. Every digital device has some sort of a CPU. This is the heart. This is what makes all the calculation, all the decisions. This is the heart of every digital device.  And every CPU, the basic building block of all CPUs are the logic gates.

Similar to your tattoo, Adam? Yeah, the logic gates. Okay, and so what is a logic gate?

Logic gate is a thing and we're going to talk about what is that thing all day. But it has inputs or it can be one input or two inputs. Inputs can be on or off.

It's normally 1 and 0. And based on those inputs and the type of the gate, we are gonna get an output.

It's very basic unit, very basic building block, get input, output, that is it. So just for example, we have a 'not' gate, a 'not' gate just flips the input. So the left side is the input, the right side is the output. If the input is 1, the output is 0. If the input is 0, the output is 1. Simple enough? Okay, we also have an 'and' gate. An 'and' gate has two inputs. And as you can understand by the name, if Input A is 1 and Input B is 1, then the output is 1. And we also have an 'or' gate, pretty much self explanatory. If input A is on or input B is on. These are the three basic gates, okay? We also have just a few more. We have the 'nand' and the 'not', 'and', 'nor', 'or'. I'm not going to get into it - it's just the flip of the 'and' and 'or', you can see by the output is just flipped out. And we also have the 'xor'. This is an interesting one I want you to remember. It's very similar to 'or', but it's called an 'exclusive or'.

If A is on, or B, but not both. Okay, and the last one we have is 'xnor', means not 'xor'. Okay, that is it.

This is the whole seven gates, the seven logic gates that every CPU has. And through these gates we play Call of Duty. There's a lot of things in the middle, but that's the way it works. Okay.

And if you wonder how do you use these gates to actually calculate things? So this is an example of how you calculate the addition of two two digit numbers and you get an output of a three digit number. We're going to get into this sketch in a second, but let's talk about building, actually building the gates.

So in your phones and your computers, the logic gates are transistors, like really small transistors, you have millions of them, like in this little patch of metal.

And they're very fast, they're doing millions of calculations every second. This is the purpose of a CPU.

But the truth is that logic gates, it doesn't have to be small, they don't have to be fast, they just have to be logical.

And you can find logic pretty much everywhere.

There's a guy called Matt Parker, he's a very famous YouTuber, he's a mathematician and a stand up guy.

About a decade ago he built a computer - an actually working computer - from dominoes and the topple of the dominoes just simulate the current of the, of the gates. A few years later, Steve Mould built a computer - sorry -built a computer from water siphons, an actual working computer made out of water.

And over the years I've seen a lot of computers made out of Legos and Lego-similar stuff. So why not with CSS?

I mean, it's only logical, right? Right.

So these are the seven gates, let's build them.

We're here to write some CSS, right? So I'm in CodePen and by the way, I'm going to give links to all of the examples here in the end of the talk. So don't worry, I'm going to do a simple gate and actually each gate is also going to have a type and I'm using an attribute selector. I'm using more and more attribute selectors lately just because I find it more semantically proper in some cases. So let's start with a simple one. Let's start with the 'not'. Okay, so we have, as we said, we have in every gate we have inputs and outputs.

So since we can have more than one input, let's have 'inputs', and inside of it let's put an 'input'. Now I said we have every input has an on or off - 1 and 0 - means it's Boolean. What type of input we have in HTML that is Boolean?

(Audience member) "Checkbox?" AS: Checkbox, thank you. So let's make this one a checkbox. Okay. And yeah, okay, as you can see, I already added some styles, we're going to get to the CSS in a second. But the second thing that we have in every gate is of course, an output, okay? So I have input, output - let's go to the CSS and see what I've done so far.

I've done the whole boring styling stuff in advance.

We're going to do the logic live.

So in the gate, just some boring style stuff. In the input, I have done this little thing. Do everybody see the code proper in the back?

Yeah? Okay, the after has the content of 0, if it's checked, it's 1. So if I check the checkbox, you can see it's one and it's changing the colors. Very simple. And in the output, I kind of did the same thing in the output, but I've done a little trick using this custom property called '--on'. So if I change the output, the '--on', excuse me, to one, you can see the output is one and it's hot pink, not deep pink. I tried to change it yesterday, I didn't like it.

Okay, so this is the thing, this is the gate itself. Nothing really important, but I also made an icon. Icon is. I drew all of these sketches in a background image just because, you know, it's CSS Day, but I'm not going to get into it. It's in the examples and if you want to see it and if you want to ask me questions about... so, be free. But I can come here to the CSS, to the HTML and I can add an icon. So now I will have... yeah, an icon. Great.

So let's write the logic for this gate, okay?

So what we have right now we need...

oops... here, let's say that I'm going to start with the 'not' gate, okay? So the '[data-type="not"'.

So how do I check if it has an input that is checked? I kind of said the answer. I'm just saying if it has an input that is checked, okay, and if this gate has an input that is checked, I want to do something with the - I want to change, excuse me - the '--on' to '1'.

Okay, so now if I'll check this box, the output is one. If I recheck it, it's very simple, but obviously the 'not' gate flips the input. So I want to add 'not' as checked. Okay, so now I have an actual working 'not' gate. Simple enough?

Great, let's continue.

It's going to get faster and faster, don't worry. So let's do the end one. And I want you to think, how would you use CSS selector to have two inputs that only if both are checked, then the 'on' is '1'. So - and by the way - in the end I have two inputs. So let's do it like this and let's come here, let's copy it.

Let's say 'and', so I don't need the 'not'.

So how do I check if I have two? And by the way, I don't think I need the input here. Just want to make it shorter because.

Yeah, it's working. So how do I check if I have two inputs that are checked?

Anybody has an idea?

Excuse me? Yeah, I can add a plus. I can add. It has a '(:checked + :checked)'.

So now, okay, if this one is checked, nothing happened. If this one is checked, nothing happened. But if they're both checked, I have a working 'and' gate.

By the way, I'm using a plus but I'd much rather use this sign (~) because right now in the HTML they're both together, maybe later on they won't be together. So okay. And of course I don't need these two different blocks because I can actually delete this thing and just add little comma.

Okay, if you have any questions, just stop me.

We have time. So I'm not going to write the rest of the HTML - it's pretty much the same.

The only thing that's changed is just the data-type. So let's do like this. And now we have all the gates here. They're all exactly the same. The only thing that's different is just the data-type. Okay, so now I have all the gates, but let's write the logic.

So the next one I want to write is of course the 'or'.

And the 'or' one is actually pretty simple: '[data-type="or"{'.

So all I need in the. What the heck?

Okay, all I need in the OR gate, I just need to check if one of them is checked.

So I just do ':checked'. Okay, so this is the 'or' if this one is checked.

Oh, oh, yep, yep, yep, yep.

Sorry. Okay, so if this one is checked, it's okay. If this one is checked, it's okay. And of course if they're both checked, it's okay.

The next two gates, as I said, is the 'not and' (nand) and 'not or' (nor).

So I'm just going to copy these two lines here. And this needs to be a column. And let's just add a 'not'.

And let's add a 'not' here. We're going to test it out in a second. So this is the not or so only if.

Oh, oh, thanks, thanks, thanks. I was testing your...

Okay, so this one, if one of them is on, it's zero, this is the 'nor', and this is the 'nor', and this is the 'nand'. So only if they're both on, it's off. Okay, now let's talk about the 'xor'.

If you remember, the 'xor' is like the 'or', but it's just either one of them. So how would you do it? Anybody want to give me an answer?

That's quiet, man. Okay, so I actually have two inputs and I just need one of them. So I'm actually checking if it has one that is checked and has one...

let's say '(input:(not:checked)'.

Okay. Oops, that doesn't need to be here.

Yep, yep, yep.

I'm missing something. I'm missing this. Okay, so now this is the 'xor' gate. If I click one it's one, that's great. If I click the other one it's great. But if they're both on, it's zero. Okay. And the last one it's oops.

So I'm just going to add a simple 'not' here. And yeah, that's it.

It's. We have X. No, X.

X. Yeah, yeah, yeah, yeah. It's okay. It's okay. It's okay.

Yeah. Okay, so now if this one is off, if this one is off, but if they're both, it's on. Great. So now we have actually working seven logic gates. And yeah, we can take these gates and build Call of Duty or whatever you want.

Yeah. No, seriously. So as I said, how are we going to take these gates and actually do something, do actual calculation with them? And to understand that, let's first talk about binary numbers because as I said, we're only working with 1 and 0 bi means 2.

I have 2 digits, 0 and 1. So if I want to count up to 5, 7 with binary numbers.

So if I have 0, it's very simple, it's 0. If I have 1, it's 1. But if I want to write 2, I write 1, 0, 3 is 1, 1, 4 is 1, 0, 0 and so on and so on. I'm not going to get really into it.

I'm just going to say that the value of each one is its position - 2 to the power of its position. I'm not going to get into a deep explanation into it, but I have made a binary to hex converter. So this is like this checkbox.

So you can actually write whatever you want and see what's the value in regular numbers.. 'regular' numbers. It's actually a nice trick. It uses counters. You can see here 2 by the power of its position. 'i' is the - its position. Okay?

Okay. So I have Binary numbers. But how do I add binary numbers?

And we're going to start with a very, at the very, very basic, let's add two single digit numbers, okay? So if I'm going to add two single digit numbers, I only have a few options.

It can be 0 plus 0, which is 0. It can be 0 plus 1, 1. 1 plus 0, again 1. Or 1 plus 1, which is 1 0. So that's all the options that I have if I'm only adding two single digit numbers. So if you see this, if you see it's like this, maybe you can kind of already understand how we can implement this calculation using logic gates. Because if we take this number and we're going to say this number is input A and we're going to take this number, we're going to say this number is input B. Okay, now we're going to look at the result. The result has two digits, the right digit. This is the sum, okay?

So the sum, the second digit is called the carry because we normally carry it if we have more digits. So if we look at the sum and we're going to look at it, it actually looks exactly like the 'xor' gate, right? 1, 0, 1, 1, 0. It's exactly like the 'xor' gate. And if we gonna take a look at the carry, it's actually 0, 0, 0, 1. Okay?

So it's exactly like the 'and' gate because only when they're both one, it's one. So I can implement this calculation using those two gates. And if I draw it out, it would actually look something like this. It's called a half adder.

And you can see I have the two inputs. Okay. And if I take those two inputs through the 'xor' gate, I get the sum, the sum digit and through the 'and', I get the carry digit.

Great. So let's build a half adder with CSS.

So I'm going to start. I have pretty much the same basic concept. I have two checkboxes. I have the carry and the sum here as the outputs. Okay. Nothing really interesting here. I just have the P, the plus and the equal sign just to show. So what I'm going to do, actually I'm going to start with the sum and the sum as I said, it's the 'xor' gate. Let's copy the 'xor' gate from here. I'm just going to copy this one here.

But I don't need this gate obviously. What I need is the half adder. Okay, so.

Oh, but yep, come on... come on.

Okay, so now if I click this one.

Okay. Oh, so now they're both on. Why are they both on? Because they're both outputs, obviously. I need to set just the sum output. So let's add a '.sum' here and now. Okay, so if I click 1, it's 1. If I click the other 1, it's still on. But if I click them both, they're off. Because this is exactly what the 'xor' gate does.

And I want to add now the 'and' gate. So again, let's do '.half-adder:has' and the 'and' is I'm going to do 'checked'.

Oops, checked. And I'm going to do find..

Checked. And now if they're both on.

And this is supposed to be of course for the carry. So now if they're both on. Yeah, it's on. If it's off, 1 plus 0 is 1, 0 plus 1 is 1, 1 plus 1 is 1 0.

We actually have a working half adder with pure CSS.

Thank you. Thank you.

Now things get a little bit weirder because we talked about single digit numbers. What happens when we go to double digit numbers? You have a lot more options.

You can't really look at it and say, "oh, this is the digit I need".

We actually, when we're adding multi numbers, like double digit numbers, we do it just like we add any regular number.

So forget about the binary for a second and let's talk about regular numbers. Okay, let's take numbers like 85 plus 47. And I know it sounds like a basic math lesson, but I'm going somewhere with it. Go with me, okay? So if I want to add those two numbers, I start with the first digit, I start with 5 plus 7. Okay, 5 plus 7 is 12, but I don't write down 12, I just write down the sum.

The first digit, it's 2, and then I carry the 1. Okay, I have the sum and the carry. And then I, when the second thing I do, I'll calculate the second digits. Okay, it's 8 plus 4 is 12. But I'm adding the carry of the first digit to the second digit. So 12 plus 1 is 13. I know it's simple, but it will make sense because this is exactly what we're going to do using binary numbers.

Okay? Because we already seen this, we have this half adder, right? This half adder adds two single digit numbers. So if I want to add two double digit numbers, I can just take this adder, I can copy it.

Okay. The sum of the first two digits, this is my first output. Okay. And the carry, this 'and' is the carry. I need to add this carry to the sum of this second output. So I'm going to add another half adder to add these two numbers, the sum of which is of course going to be the third number. And all I need to do is just add those carries and this is the third number. So this is called a full adder.

This is how we add... we do addition for two digit numbers. So let's build it.

Yeah, so I have here pretty much in the HTML, pretty much the same thing, but I have added one thing. I've added a data-digit because I have two digits now in every number and the value of each digit is different. So I want to know which one of those digits is checked, okay?

So this is the only thing I added.

So let's go to the logic.

So I was planning to write everything like live and then I saw yesterday that everybody just - uncommon things and it looks so much more comfortable.

So this is the first number. Okay, I'm doing. This is the problem. I'm doing. I have like. You know what? You know what? Yeah, Chris, this is when I do. Wait, wait just one second. I'm going to go back to the, to the regular one.

I'm going to change it to this view and then I'm going to change it to this view. So it would be easier. Right? Yeah.

Okay, so this is the first one. Okay, I have the full adder. I'm asking if it has the digit '1' that is checked and another digit '1' that is not checked, because it's 'xor'. So the sum one, the first number should be, should be on. So if this one is on, this is on. And if this one is on, this is on. But if they're both on, it's off because we are carrying the one to here. Okay, so this...

Actually, let's go back here. Okay, so this is what we've done. Okay, the first one. Now the thing is that I need to add these two, but in order to add these two first I need to calculate the value for each one. So I'm going to calculate it and I'm going to save the value of each one of those gates in a custom property.

Okay. And then I'm going to combine these two custom properties. So here.

Okay, this is the first 'and' gate. I'm asking if the first digit is checked and it has another checked first digit after it. So the 'and' equals '1'. Okay, I'm just as - again, I'm saving the '1' as a custom property. I'm not actually doing anything with it for now. And then...

So then I'm going to can calculate the floor of the second number of the second digit. Okay? It's very similar to this one, only I'm not setting anything to the sum, I'm just saving a custom property.

So now I actually have the value of these two gates saved in custom properties. So now I have to set this gate, but I can't do it with selectors because I don't have the data in selectors, I have the data in custom property. So how do I make a 'xor' gate with custom property? Anybody has an idea? Math!

Yeah, that's the easy way. So what I'm going to do. But how in math, by the way, do you know?

Yeah. Okay, so think about, I have two numbers, I have two variables, okay? And I want that only if one of them is '1', I want the response to be '1'.

So what I can do here, it's a simple calc, I can do a 'var'. The first var is '(--_and1)'. Right?

And let's give it a default of zero. And we're gonna do plus.

Okay, and it's gonna be weird for a second, we're gonna do and '(--_xor2)'.

Okay, so now I actually have if one of them is 1, it's okay, I have 1. But if they're both 1, I have 2, and I don't want 2. The 2 needs to be 0.

Luckily we have trig functions in CSS, so I can do just like the 'mod' function comma 2. And now it's xor gate.

Okay, so now if I add 1, it's 1. And if I add this 1 it's okay. And if I add it both I get the xor gate for the sum. For the sum2. Okay, so this is actually, this is what we've done. We actually put this thing. And the last thing we need to do is to first calculate this gate.

This is the 'and2'. And then we need to add it to this 'and'.

Okay, so yeah, let's come here. So this is the second gate. It's again very similar to this and1.

I'm just changing the digit to 2 and I'm saving the number 2 - and2. And. And okay, and the last thing I'm calculating.. last thing I'm calculating the and3 exactly like.. I'm calculating 'and' by multiplying two variables. Because if the variable one is 1 and the second is zero, I get zero, but only if they're both 1, I get the result of 1.

So here to calculate the and I have the and1 x xor two. And as I said, in the and, I'm just adding those two ands to the final result. So now, if I haven't forgotten anything except deleting this one, we kind of have a full adder. So if it's zero plus 1, it's okay.

If it's 1, it's okay. It's going through here to here. It's an actual working full adder. Okay, so. And it kind of looks weird, but as more complicated as you go, it gets way weirder. And I went up to five digits because once you go about five, it's just pretty much the same, but it's an actual working example. You can add whatever you want and it's working.

In terms of code, I pretty much did the same thing I've done in two. So I have the digit from 5 to 1, 5 to 1. I've got the outputs. In terms of CSS, it's kind of the same CSS that we've seen so far, just way, way longer because I have much more calculation, but again, it's really pretty much repeating itself. If I would use Sass, then maybe I would use a loop or something. But don't build a computer with Sass.

Yeah. Any questions, by the way? I normally take questions live.

I'm sorry. I'm sorry. Yeah.

Okay, so, yeah, so this is. This is a half adder. And this is the base for pretty much every calculation, because once you can add numbers, you can do calculations, and from there you can pretty much go wherever you want. So just to finalize what we've done so far, I just want to start with the question that we talked about in the very, very beginning.

Is CSS a programming language? By the way, what do you think? Is CSS a programming language? Yes, it is a programming language. Okay. And I don't know why people think it doesn't, but nevermind. Can we build a computer with CSS?

I mean, it's not very efficient, it's not very fast, definitely not practical, but yes, we can build a computer with CSS. And by the way, you can take it, like all the way Turing-complete and do whatever you want with it. I didn't go all that far because you know why?

And the last question is, do you all think CSS is way cooler now that you know that you can build a computer with CSS?

Yes. No. No, actually, it wasn't strong enough. Do you think?

Okay, now it's even better.

Yeah. So thank you, guys. I was Amit. If you want.. all of the examples that I've seen is in this link, if you want it. And thank you.

Bramus: Amit... AS: One thing that I forgot. Say hi (takes selfie with audience).

Yeah, okay. Now I'm yours. Bramus: Okay, cool. Amit, please join me in the corner with the lovely flowers.

Where's Counter Strike? You promised us Counter Strike.

AS: Oh, next year. Bramus: Okay, so we now let you code until next year. AS: Not Counter Strike, Call of Duty. Bramus: Call of Duty. Sorry, sorry, I'm a bit older. Somebody else asked, "But can it run Doom?" AS: Oh yeah, they've done Doom on Typescript, right? Yeah, and then PDFs. And there's also a CSS Doom, if I'm not mistaken. Oh, there's a what Doom? Email Doom. No, Ben Evans did like a maze Doom..

Ish thing. Crazy. Bramus: Obvious question - I think you mentioned. "Is CSS Turing-complete?" AS: Well, theoretically, yeah. You could take it all the way up there.

Once you can calculate logic gates, so you could calculate everything, it would be slow. I don't think it would be slower than the first computer, but it's going to be slow.

So yeah, theoretically, yeah, you could. Yeah.

Bramus: I bet that we have some Chrome engineers here in the room and when they saw the selectors pass by on the screen, I think they might have had a heart attack, like please don't write us. AS: I have a tendency to use those things to push them to the max. Bramus: But also then again, your DOM size is pretty small, so it doesn't really matter, in that case. Speaking of the selectors, we had two questions on this. You have used 'has' - our favorite selector, I think, a lot. Would you be able to build this without has? AS: So theoretically, yeah. But you would need to change the structure.

I wanted the structure to be more obvious, more readable and I prefer to use has and to have this structure and not do it the other way. Bramus: And what would be the other structure? AS: Well, you can have - once you have those two checkpoint, if you have the two inputs and the output like in the same.. in the same container. So no problem.

But of course the output should be after it because the orders of the input doesn't really matter when you build a gate. Bramus: Okay, I'm trying to follow. Are you then suggesting to like if you can. I've used this thing before, so maybe that's what you're hinting at, I'm not sure. And where you put the inputs like way at the top in your body and then you have the labels point to them using the ID attributes? AS: Yeah, that's a hack way to do it. But you can just put the input where you put the labels like the input, input, output in the same container.

If you want to put them outside, you can. Then you put the labels in.

Then you just use the hack of the label. Bramus; But then I would also assume that getting to it wasn't Counter Strike. Which one was it again?

AS: Call of Duty. Bramus: Call of Duty. Getting to Call of Duty would be way more complicated. AS: Yeah. And I think it would be less readable.

It would be. It's not going to be visible anyway. Bramus: Challenge, by the way, can you make this scroll driven? Scroll, scroll driven. As you're scrolling, it's adding up the numbers. AS: I'll do it later.

Bramus: Ok. Give him five minutes. He'll do it.

You've made a bunch of very nice demos online. You've shown us the CPU one. Are there other demos? Like I've seen your CodePen I'm not sure if everybody has seen Amit's CodePen. Are there some other demos that you would like to show to people and say like, hey, this one was really cool or this one has a very nice outcome.

And don't say all of them. AS: It's like asking, what's your favorite child? I don't know.

My pens are exploration - I try things and sometimes I get to things that looks really cool and amazing and sometimes it's like boring stuff. Like lately I've done a lot of optical illusions with CSS.

Bramus: Optical illusions. Such as?

AS: I can show you. Bramus: Yeah, show me. Show us where we're all.

Do you want to see new tab codepen.io/amitsheen.

Go for it. AS: Sorry, it's not me. So let's go to my CodePen. If you talked about my CodePen.

So one of the latest thing I've done. This is.

I think one of you told me to do it. I don't remember who it was. Oh, it was Roland. He's not here today. I've done.

Oh, I've done this one that you can actually. It's pure CSS.

It's single div that when you click on it. Let's go to full page view. Let's. Okay, so when you click on it, it's only squares.

There's no crooked lines. But I'm betting that you see the lines a bit quicker.

But when I click on it, it moves and trust me, there's only squares here. Bramus: Okay, and how many lines of CSS is that? AS: Not a lot.. less than. Bramus: Don't say. It's also one declaration and AS: No, no less than you would think.

The CSS part is.. Let's go again to this. Bramus: Is it like border-style: crooked crooked or... AS: No. So it's 53 lines.

It's done with clip-path mainly. Bramus: Does anybody understand this besides Amit?

Okay, I see three hands getting raised right now.

Cool. Show us another one. Amit, show us another one.

AS: What's your favorite? Bramus: I saw the one where you had here the proximity reactions one.  AS: Yeah we talked about it - I really am really trying to push that. We're going to get the mouse position, the X, Y mouse position in our CSS because why not?

So I have done this little experiment that when you move, they change. I actually done. It's not... I've done it before, but I've done it with JavaScript. Okay.

So this is JavaScript. All of the calculation here is done with JavaScript. And after I did this one, I said, you know what, if I have the numbers in CSS, I have all the trig functions in CSS, so I can just do it with pure CSS. So I've done the other one.

I've done this one. By the way, there is. I think there's a few more optical illusions here. You can see I'm doing a lot of weird stuff whenever I can. This is. By the way, I talked to the guy with the CSS. It's here, right? Bramus: He's here. Sasha is here somewhere. Sasha, where are you? AS: I've done the animation for the State of CSS, these ones and I'm doing a lot of weird animation stuff. Bramus: Was that also only one div or no? AS: Don't be crazy.

You like it? Bramus: I think - where's Julia? Where's Julia?

I see you here way at the back. Way at the back. Yeah. Last year you explained this to us, right? How you built this type of thing.

AS: Yeah. If you don't know, Julia's work is even better.

I don't know if anything...

Bramus: Could you go back to the one where you had the CSS version of the lights going around and stuff? Maybe you can.

And sorry for putting on the spot here. Maybe you can talk a little bit more about it. Because what I think is going on, you have a bit of JavaScript you said? AS: Yeah. So all the JavaScript is doing here is just: It's two lines of JavaScript. I'm just setting the two custom properties, mx and my. Okay. I'm just putting the value of them and everything else is happening inside of CSS.

So it looks like this. Maybe I would make it a bit bigger. Bramus: I see a 'atan', I see 'cosine', I see 'sine'. AS: I have pretty much whatever I could. Yeah. So I'm calculating The distance of the mouse position from the element. I first calculate the position of the element according to its index, because all I have here in the HTML is just the index.

And so I calculated its position through the index, and then I calculate the distance of the mouse position from that position. So, then according to the distance and according to the angle, the reaction changes. Bramus: How do you do the shadows?

AS: Oh, the shadows are great. This is a great. Oh, yeah, yeah. Thank you. So I'm actually. Yeah, so it's a good question because if I'm far away from the shadow, you can see the shadow is narrower, and if I'm closer away, it becomes wider. So I was. How do I do it? Okay, so the first thing I went to, like, clip-path and try to make all these calculation, but then I said, we have perspective in CSS.

So what I'm actually doing is I have, like, this element, this black element that I'm rotating on the.

It's not here. Where's the shadow? This is the ball. This is the shadow.

I'm rotating it on the Y axis. Okay. So when you look at the bottom part. Okay. When it's straight, it looks narrow.

When I rotate it, the top part looks wider.

So I'm actually using perspective to fake shadows if it makes sense? Bramus: It's so cool. AS: Thanks. Bramus: Do you think this is cool? Clap it up. Come on, clap it up! AS: Thank you!

Bramus: I see there there's a lot of maths involved in these Amit, like, probably like most of you back in this, in the day when we had math at school, you were like, "I'm not following this." Did you follow some special courses around this later on?

Or you just, like, looked it up and then applied? Or were you one of the few people back in the mathematics classes that was like, "oh, yeah, I should remember this for later on." AS: I'm the weird guy in math class that tell the teacher that she was wrong.

Okay, yeah, that's me.

I didn't learn, like, in actual, you know, school, not to code, not math and nothing. It's everything. Trial and error.

Bramus: Are there resources out there that people can check? Like. Because, like, for you, you just see it and, you know, this is a sine, this is a cosine. If I look at this, I'm like, "yeah.. maybe?" AS: There's not. I can't think, like, of one single source. It's just, you know, Google. Google it. There's so many resources out there. Just find the one for you.

I haven't looked for resources on that topic for years.

So I don't, I don't know any specific one to recommend. Sorry. Bramus: Maybe you could provide the resources? AS: Oh, there is, there is one. Michelle, right? Michelle wrote an amazing three piece article a few years ago, two years ago.. about trigonometry for CSS developers, right? Something like that. And.. oh, it's amazing.

Go on Codrop. Bramus: On Codrop. Check it out.

Cool. AS: CSS in real life. Check it out. Bramus: Does anybody have more questions for Amit or are we all like super perplexed by all the things that we saw? I think we're a bit in that state. So please, once again, thank you, Amit. AS: Thank you.

Building a CPU with CSS

Amit Sheen

A little back story...

Illustration of a group of developers sitting at tables in a bar, with a large projection of source code displayed on the wall behind them.

Is CSS a programing language?

Illustration of a group of people sitting around tables in a bar, with a large speech bubble containing the question "Is CSS a programing language?" and computer code projected on the wall in the background.

Of course it is!

Illustration showing a group of people sitting at tables in a bar, with computer code projected on the background wall. A speech bubble in the scene contains the phrase "Of course it is!"
Of course it is! I can build a computer with pure CSS...
Illustration of a group of people sitting in a bar, with code visible in the background and a speech bubble highlighting the statement about building a computer with CSS.

No you can't!

Illustration of a group of people sitting around a large table in a dimly lit bar or café, with a speech bubble pointing to one seated figure and displaying the text "No you can't!". Computer code is faintly visible overlaid onto the scene.

Yes I can!!!

Illustration of people sitting around a table in a dimly lit room, with a code editor projected in the background and a speech bubble in the center containing the text "Yes I can!!!".

Dive into the CPU

Dive into the CPU

Logic gate

Illustration of a large brain with an open gate at its base, symbolizing a "logic gate".

Dive into the CPU

Logic gate

  • Input(s) → output
Diagram showing a large arrow labeled "Input(s)" pointing to a central image of a brain with a doorway labeled "Logic gate", which then points to another large arrow labeled "output".

Dive into the CPU

  • Not
    • i | o
    • 1 | 0
    • 0 | 1
  • And
    • i | o
    • 0 0 | 0
    • 0 1 | 0
    • 1 0 | 0
    • 1 1 | 1
  • Or
    • i | o
    • 0 0 | 0
    • 0 1 | 1
    • 1 0 | 1
    • 1 1 | 1
  • Nand
    • i | o
    • 0 0 | 1
    • 0 1 | 1
    • 1 0 | 1
    • 1 1 | 0
  • Nor
    • i | o
    • 0 0 | 1
    • 0 1 | 0
    • 1 0 | 0
    • 1 1 | 0
  • Xor
    • i | o
    • 0 0 | 0
    • 0 1 | 1
    • 1 0 | 1
    • 1 1 | 0
  • Xnor
    • i | o
    • 0 0 | 1
    • 0 1 | 0
    • 1 0 | 0
    • 1 1 | 1
Diagram showing seven logic gates—Not, And, Or, Nand, Nor, Xor, and Xnor. Each gate is illustrated with its electronic symbol and accompanied by a truth table displaying inputs and outputs.

Dive into the CPU

Diagram illustrating a digital logic circuit composed of interconnected AND, OR, and XOR gates, representing an example of how a CPU processes binary addition or similar logic operations. Input and output nodes are shown as colored circles.

Building the gates

Building the gates

A collage of five images: a server room, a large layout of dominoes arranged in a circuit pattern surrounded by people, a pneumatic logic gate model, a LEGO model resembling a computer lab or office, and a large CSS logo.

CSS Logic Gates

Screenshot of a CodePen editor with the main file showing the heading "CSS Logic Gates".

CSS Logic Gates

<h1>CSS Logic Gates</h1>
		
				<div class="gate" data-type="not">
		
				</div>
				
Screenshot of a code editor displaying HTML for a heading and a div element representing a CSS logic gate (type "not").

CSS Logic Gates

<h1>CSS Logic Gates</h1>
		
				<div class="gate" data-type="not">
					<div class="inputs">
						input
					</div>
				</div>
				
Screenshot of an in-browser HTML editor showing a code example for a CSS logic gate, with a live preview displaying the heading "CSS Logic Gates" and the word "input".

CSS Logic Gates

<h1>CSS Logic Gates</h1>
		
				<div class="gate" data-type="not">
					<div class="inputs">
						<input type="checkbox">
					</div>
				</div>
				
Screenshot of a code editor (showing HTML code for a CSS logic gate) beside a web preview rendering the heading "CSS Logic Gates" and a box with the digit "0".

CSS Logic Gates

<h1>CSS Logic Gates</h1>
				<div class="gate" data-type="not">
					<div class="inputs">
						<input type="checkbox">
					</div>
					<output></output>
				</div>
				
Screenshot of a live coding environment with the left pane showing HTML code for a NOT logic gate using CSS, and the right pane previewing the output with the title "CSS Logic Gates" and two boxes each containing a 0.

CSS Logic Gates

Screenshot of a code editor (likely CodePen) with a CSS file open on the left and a visual representation of two logic gate inputs on the right, each displaying a value of 0.

CSS Logic Gates

Screenshot of a code playground interface showing CSS code for customizing checkboxes on the left, and a live preview on the right with two styled checkboxes labeled "0".

CSS Logic Gates

Screenshot of a code editor (showing CSS code) and a demo interface for CSS logic gates with two input elements labeled "0".

CSS Logic Gates

Screenshot of a code editor (likely CodePen) on the left displaying CSS for logic gate styling, alongside a web preview on the right demonstrating two toggle buttons labeled "0" for a CSS Logic Gates demo.

CSS Logic Gates


				&:after {
					content: var(--content, '0');
					font-size: 2em;
				}
				&:checked {
					--content: '1';
					background-color: limegreen;
					border-color: green;
					color: #333;
				}
				
VS Code-like code editor screenshot showing CSS for toggling a value, alongside a webpage preview with heading "CSS Logic Gates" and two logic gate buttons displaying states "1" (active, green) and "0" (inactive, gray).

CSS Logic Gates

Screenshot of an online code editor displaying CSS code on the left and an interactive demonstration of logic gate outputs using highlighted "1" and "0" indicators on the right.

CSS Logic Gates

Screenshot of a code editor displaying CSS code for styling an output element, alongside a preview showing two circular indicators labeled "1" (green) and "0" (gray) under the heading "CSS Logic Gates".

CSS Logic Gates


				output {
					display: grid;
					place-items: center;
					width: 3em; height: 3em;
					background-color: hotpink;
					color: maroon;
					border-radius: 50%;
					border: 2px solid maroon;
					filter: grayscale(calc(1 - var(--on, 0))) invert(calc(1 - var(--on, 0)));
					&:after {
						counter-reset: content var(--on, 0);
						content: counter(content);
						font-size: 2em;
					}
				}
				
Screenshot of a code editor showing CSS code for output styling, alongside a preview of CSS logic gates with a green "1" and a gray "0" displayed.

CSS Logic Gates


				output {
					--on: 1;
					display: grid;
					place-items: center;
					width: 3em; height: 3em;
					background-color: hotpink;
					color: maroon;
					border-radius: 50%;
					border: 2px solid maroon;
					filter: grayscale(calc(1 - var(--on, 0))) invert(calc(1 - var(--on, 0)));
					&::after {
						counter-reset: content var(--on, 0);
						content: counter(content);
					}
				}
				
Screenshot of a code editor displaying CSS code for a logic gate, alongside a visual interface showing two boxes labeled "1"; one green and one pink, illustrating binary output states.

Building the gates

Table showing seven logic gates (Not, And, Or, Nand, Nor, Xor, Xnor) with each gate's circuit diagram and associated truth table for their input and output combinations.

CSS Logic Gates

Screenshot of a code editor showing CSS code for .icon and logic gate types ("buffer" and "not") alongside a visual preview of two logic gate inputs, labeled 1 (green) and 0 (grey), under the heading "CSS Logic Gates".

CSS Logic Gates

<h1>CSS Logic Gates</h1>
		
				<div class="gate" data-type="not">
					<div class="inputs">
						<input type="checkbox">
					</div>
					<div class="icon"></div>
					<output></output>
				</div>
				
Screenshot of a code editor displaying HTML for a CSS logic gate, with a live preview pane showing a visual representation of a NOT gate with an input and output.

CSS Logic Gates


				[data-type="not"]:has(input:checked) {
					--on: 1;
				}
				
Split view: On the left, a code editor shows CSS for a NOT logic gate using the :has() selector. On the right, a visual diagram displays a NOT gate symbol with an input square (green, labeled 1) feeding into the gate and an output circle (pink, labeled 1), representing the gate's output. This illustrates the CSS logic and its live result.

CSS Logic Gates


				[data-type="not"]:not(:has(input:checked)) {
					--on: 1;
				}
				
Diagram showing a NOT logic gate: a 0 input is transformed into a 1 output, visually represented with boxes and a NOT gate symbol.

CSS Logic Gates

Screenshot of an online code editor showing HTML code for a NOT logic gate, with a live preview illustrating a NOT gate where an input of 0 produces an output of 1.

CSS Logic Gates

Screenshot of a code editor displaying HTML for logic gates alongside an interface showing two visual logic gate diagrams with input and output values.

CSS Logic Gates

Screenshot of a code editor with CSS code on the left and a visual representation of logic gates (NOT and AND) with binary inputs and outputs on the right.

CSS Logic Gates


				/* LOGIC */
				[data-type="not"]:not(:has(input:checked)) {
					--on: 1;
				}
				[data-type="not"]:not(:has(input:checked)) {
					--on: 1;
				}
				
Diagram displaying two CSS logic gate representations: The first shows a NOT gate with an input of 0 and output of 1. The second shows an AND gate with two inputs of 0 and output of 0.

CSS Logic Gates


				/* LOGIC */
				[data-type="not"]:not(:has(input:checked)) {
					--on: 1;
				}
				[data-type="and"]:has(input:checked) {
					--on: 1;
				}
				
Screenshot of a CodePen interface showing CSS code for implementing logic gates and a visual demonstration of NOT and AND gates with input and output indicators.

CSS Logic Gates


				/* LOGIC */
				[data-type="not"]:not(:has(:checked)) {
					--on: 1;
				}
				[data-type="and"]:has(input:checked) {
					--on: 1;
				}
				
Diagram showing two types of logic gates: - A NOT gate with a single binary input (1) producing an output (0). - An AND gate with two binary inputs (both 0) producing an output (0).

CSS Logic Gates

Screenshot of a code editor displaying CSS logic for "not" and "and" gates, alongside diagrammatic representations of a NOT gate and an AND gate with binary inputs and outputs.

CSS Logic Gates


				/* LOGIC */
				[data-type="not"]:not(:has(:checked)) {
					--on: 1;
				}
				[data-type="and"]:has(:checked + :checked) {
					--on: 1;
				}
				
Diagram illustrating two CSS logic gates: a NOT gate with a single input (0) leading to an output (1), and an AND gate with two inputs (both 1) also leading to an output (1). The logic is visualized alongside the relevant CSS code implementing the gates.

CSS Logic Gates


				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked) {
					--on: 1;
				}
				
Split screen: On the left, a code editor shows CSS for logic gates. On the right, two logic gate diagrams are shown: the first depicts a NOT gate converting an input of 0 to 1, and the second shows an AND gate with two inputs of 1, resulting in an output of 1. Visual gate symbols are used for clarity.

CSS Logic Gates

<div class="gate" data-type="and">
					<div class="inputs">
						<input type="checkbox">
						<input type="checkbox">
					</div>
					<div class="icon"></div>
					<output></output>
				</div>
		
				<div class="gate" data-type="or">
					<div class="inputs">
						<input type="checkbox">
						<input type="checkbox">
					</div>
					<div class="icon"></div>
					<output></output>
				</div>
				
Diagram showing two types of logic gates with their inputs and outputs. The first row illustrates a NOT gate with a single input of 0 (unchecked checkbox) and an output of 1. The second row shows an AND gate with two inputs, both set to 1 (checked checkboxes), and the output is 1.

CSS Logic Gates

Split-screen screenshot: On the left, a code editor shows HTML code for logic gate inputs and icons; on the right, a web preview displays a vertical list of logic gates with visual diagrams—NOT, AND, OR, and XOR—each with toggleable binary inputs and outputs, demonstrating digital logic gate functionality rendered in CSS.
<div class="gate" data-type="xnor">
					<div class="inputs">
						<input type="checkbox">
						<input type="checkbox">
					</div>
					<div class="icon"></div>
					<output></output>
				</div>
				
Screenshot of a code editor showing an HTML snippet for a logic gate, with a sidebar containing diagrams of various logic gates.

CSS Logic Gates


				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked) {
					--on: 1;
				}
				
Split screen showing: on the left, a code editor with CSS code implementing logic gates using attribute selectors and the :has() pseudo-class. On the right, a diagram visually demonstrating logic gate behavior (NOT, AND, OR) with boxes representing binary inputs (0 or 1), inputs shown as switches, and stylized gate symbols; the outputs are binary (0 or 1). One row shows an active input (1) that changes the gate’s output.

CSS Logic Gates


				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked) {
					--on: 1;
				}
				
Screenshot of a code editor showing CSS for logic gates, alongside a visual interface demonstrating logic gate operations (NOT, AND, OR) with input switches and output indicators.

				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked),
				[data-type="and"]:not(:has(:checked ~ :checked)),
				[data-type="or"]:not(:has(:checked)) {
					--on: 1;
				}
				
Split screen showing a code editor with logic gate CSS code on the left, and on the right, a diagram of digital logic gates ("NOT", "AND", "OR") with labeled binary inputs and outputs visualized per gate as 0s and 1s. The diagram illustrates how different input combinations affect gate outputs, using both boxes and gate icons.

				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked),
				[data-type="nand"]:not(:has(:checked ~ :checked)),
				[data-type="nor"]:not(:has(:checked)) {
					--on: 1;
				}
				
Screenshot of a code editor (CodePen) showing CSS logic for digital logic gates, alongside a visual diagram of logic gates with binary inputs and outputs, representing NOT, AND, OR, NAND, and NOR gate behaviors using checkbox inputs and output indicators.

				.icon {}
				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked),
				[data-type="nand"]:not(:has(:checked ~ :checked)),
				[data-type="nor"]:not(:has(:checked)),
				[data-type="or"]:has(:checked) {
					--on: 1;
				}
				
Live coding environment showing CSS code for logic gates. On the right, a diagram visualizes digital logic gate inputs and outputs with interactive states.

				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked),
				[data-type="nand"]:not(:has(:checked ~ :checked)),
				[data-type="nor"]:not(:has(:checked)),
				[data-type="xor"]:has(:checked):has(input:not(:checked)),
				--on: 1;
				
Screenshot of a code editor with CSS logic for binary gates on the left, and a logic gate diagram table on the right showing input and output states (0 or 1) for various gates, with icons visually representing the gates and their current input/output values.

				.icon {}
				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked),
				[data-type="nand"]:not(:has(:checked ~ :checked)),
				[data-type="nor"]:not(:has(:checked)),
				[data-type="xor"]:has(:checked):has(input:not(:checked)) {
					--on: 1;
				}
				
Screenshot of a code editor displaying CSS code for logic gate behavior (NOT, AND, OR, NAND, NOR, XOR), alongside a visual interactive diagram of logic gates with input and output states represented by buttons and icons.

				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked),
				[data-type="nand"]:not(:has(:checked ~ :checked)),
				[data-type="nor"]:not(:has(:checked)),
				[data-type="xor"]:has(:checked):has(input:not(:checked)),
				[data-type="xnor"]:not(:has(:checked):has(input:not(:checked))) {
					--on: 1;
				}
				
Screenshot of a code editor showing CSS logic gate selector code, alongside a visual simulation of logic gates with binary inputs and outputs.

				/* LOGIC */
				[data-type="not"]:not(:has(:checked)),
				[data-type="and"]:has(:checked ~ :checked),
				[data-type="or"]:has(:checked),
				[data-type="nand"]:not(:has(:checked ~ :checked)),
				[data-type="nor"]:not(:has(:checked)),
				[data-type="xor"]:has(:checked):has(input:not(:checked)),
				[data-type="xnor"]:not(:has(:checked)):has(input:not(:checked)) {
					--on: 1;
				}
				
VS Code-like code editor showing CSS logic for logic gate simulation. To the right, visual diagram of digital logic gates (AND, OR, NAND, NOR, XOR, XNOR) with two binary inputs and an output, each gate represented with typical logic gate symbols and colored boxes for input and output states.

Binary numbers

  • 0 = 00000
  • 1 = 00001
  • 2 = 00010
  • 3 = 00011
  • 4 = 00100
  • 5 = 00101
  • 6 = 00110
  • 7 = 00111
  • 8 = 01000
  • 9 = 01001
  • 10 = 01010
  • 11 = 01011
  • 12 = 01100
  • 13 = 01101
  • 14 = 01110
  • 15 = 01111
  • 16 = 10000
  • ...
<div class="container">
					<input type="checkbox" style="--i: 5">
					<input type="checkbox" style="--i: 4">
					<input type="checkbox" style="--i: 3">
					<input type="checkbox" style="--i: 2">
					<input type="checkbox" style="--i: 1">
					<input type="checkbox" style="--i: 0">
					<output></output>
				</div>
				

000110 = 6

Screenshot of a code playground showing HTML for interactive checkboxes, and a binary-to-decimal conversion display with the binary value "000110" equaling decimal 6.

Adding binary numbers

  • 0 + 0 = 00
  • 0 + 1 = 01
  • 1 + 0 = 01
  • 1 + 1 = 10

Adding binary numbers

  • 0 + 0 = 00
  • 0 + 1 = 01
  • 1 + 0 = 01
  • 1 + 1 = 10
Diagram showing a table with pairs of binary digits being added together, demonstrating the possible outcomes for single binary digit addition.

Adding binary numbers

  • 0 + 0 = 0
  • 0 + 1 = 1
  • 1 + 0 = 1
  • 1 + 1 = 10
Diagram showing a table of binary addition examples: pairs of binary digits (0 or 1) are visually grouped in columns with a plus sign and equal sign, showing their sum results; the final case (1 + 1 = 10) illustrates carry in binary addition.

Adding binary numbers

  • 0 + 0 = 0
  • 0 + 1 = 1
  • 1 + 0 = 1
  • 1 + 1 = 10

Xor


				i o
				0 0 : 0
				0 1 : 1
				1 0 : 1
				1 1 : 0
				
Diagram showing binary addition pairs and their results alongside a logic diagram for an XOR gate and its truth table.

Adding binary numbers

  • 0 + 0 = 00
  • 0 + 1 = 01
  • 1 + 0 = 01
  • 1 + 1 = 10

Xor


				i	o	o
				0 0 : 0
				0 1 : 1
				1 0 : 1
				1 1 : 0
				
Diagram showing binary addition results in columns, alongside an XOR gate diagram with its truth table.

Adding binary numbers

  • And
    • i  o
      				0 0:0
      				0 1:0
      				1 0:0
      				1 1:1
  • Xor
    • i  o
      				0 0:0
      				0 1:1
      				1 0:1
      				1 1:0
  • Binary addition examples:
    • 0 + 0 = 00
    • 0 + 1 = 01
    • 1 + 0 = 01
    • 1 + 1 = 10
Diagram showing the logic gate symbols and truth tables for AND and XOR gates on opposite sides of the slide, with binary addition examples in the center showing how two input bits add to produce sum and carry outputs.

Adding binary numbers

  • 0 + 0 = 00
  • 0 + 1 = 01
  • 1 + 0 = 01
  • 1 + 1 = 10
Diagram of a half adder circuit: two inputs feed into an XOR gate to produce the sum output (S), and into an AND gate to produce the carry output (C).

CSS Half adder

<h1>CSS Half adder</h1>
		
				<div class="half-adder">
					<input type="checkbox">
					<p>+</p>
					<input type="checkbox">
					<p>=</p>
					<output class="carry"></output>
					<output class="sum"></output>
				</div>
				
Screenshot of a code editor on the left displaying HTML code for a CSS Half adder, with a live preview on the right showing two input boxes labeled with zeros, a plus sign, an equal sign, and two output circles representing carry and sum outputs.

CSS Half adder


				.half-adder:has(:checked):has(input:not(:checked)) {
					--on: 1;
				}
				
Split-screen screenshot showing a CodePen interface: on the left, a code editor displays CSS code for a half-adder logic circuit; on the right, a simulation labeled "CSS Half adder" displays two binary inputs (0 and 1), a plus sign, and two pink circles labeled 1, representing the binary sum and carry outputs.

CSS Half adder


				*, ::before, ::after {…}
				body {…}
				.half-adder {…}
				/* LOGIC */
				.half-adder:has(:checked):has(input:not(:checked)) .sum {
					--on: 1;
				}
				
Split-slide screenshot showing a panel with CSS code for a half adder logic circuit (in CodePen) on the left, and a visual interactive diagram labeled "CSS Half adder" on the right, displaying two green squares with "1 + 1" and two gray circles indicating output values "0 0".

CSS Half adder


				/* LOGIC */
				.half-adder:has(:checked):has(input:not(:checked)) .sum,
				.half-adder:has(:checked ~ :checked) .carry {
					--on: 1;
				}
				
Screenshot of a code editor showing CSS code for a half adder, alongside a visual diagram that represents a binary addition: two input boxes (one green and checked with "1", one gray and not checked with "0"), a plus sign, and the output values (the sum showing "1", the carry showing "0").

CSS Half adder

Split screen showing CSS code for logic gates on the left and a visual demonstration of a CSS Half adder on the right, with two green boxes labeled "1", a plus sign, then an equals sign, a red box labeled "1", and a gray box labeled "0", illustrating binary addition and carry in a half-adder circuit.

Adding binary numbers

  • 00 + 00 = 000
  • 00 + 01 = 001
  • 00 + 10 = 010
  • 00 + 11 = 011
  • 01 + 00 = 001
  • 01 + 01 = 010
  • 01 + 10 = 011
  • 01 + 11 = 100
  • 10 + 00 = 010
  • 10 + 01 = 011
  • 10 + 10 = 100
  • 10 + 11 = 101
  • 11 + 00 = 011
  • 11 + 01 = 100
  • 11 + 10 = 101
  • 11 + 11 = 110

Adding numbers

85
47 +

Adding numbers

85
47
+
Mathematical illustration showing the numbers 85 and 47 arranged for vertical addition, with the rightmost digits (5 and 7) outlined in red to emphasize column-wise addition.

Adding numbers

1
 85
+ 47

2

Adding numbers

Illustration showing vertical addition of two decimal numbers, 85 and 47, with the tens column (8 and 4) outlined in red, a carry of 1 above the tens column, and the sum's units digit (2) placed below a yellow line. The word "binary" in the title is crossed out to emphasize that this is decimal addition.

Adding numbers

1
85
47  +

132
Diagram showing a vertical addition of two decimal numbers (85 and 47) resulting in 132, with a carry '1' written above the leftmost column.

Adding binary numbers

Logic circuit diagram illustrating the process of adding binary numbers using a series of logic gates (AND, OR, XOR). The diagram shows how input lines feed into the gates across multiple rows, visually representing the construction of a multi-bit adder (such as a full adder circuit) with outputs at the right edge.

CSS Full adder

<h1>CSS Full adder</h1>
		
				<div class="full-adder">
					<input type="checkbox" data-digit="2">
					<input type="checkbox" data-digit="1">
					<p></p>
					<input type="checkbox" data-digit="2">
					<input type="checkbox" data-digit="1">
					<p></p>
					<output class="carry"></output>
					<output class="sum2"></output>
					<output class="sum1"></output>
				</div>
				
VS Code editor showing HTML code for a CSS-based full adder, alongside a visual simulation of a full adder interface with two sets of two-digit binary inputs and displayed output boxes.

				*, *::before, *::after {}
				body {}
				.full-adder {}
				/* LOGIC */
				.full-adder:has([data-digit="1"]:checked):has([data-digit="1"]:not(:checked)) {
					--on: 1;
				}
				
Split-screen screenshot showing the CodePen editor with CSS code for a full adder circuit on the left, and a visual simulation of a binary addition circuit on the right.

				.full-adder:has([data-digit="1"]:checked):has([data-digit="1"]:not(:checked)) .sum1 {
					--on: 1;
				}
				

CSS Full adder

Screenshot of a code editor showing CSS logic for a full adder, along with a visual diagram of two sets of binary digits being added, resulting in a three-digit binary sum.

Adding binary numbers

Diagram showing a multi-bit binary adder constructed from logic gates (AND, OR, XOR). Multiple inputs are processed through a series of interconnected gates, illustrating how binary addition and carry operations are handled using logic gates.

Adding binary numbers

Diagram showing logic gates (AND and OR gates) representing the process of adding binary numbers. Several input lines feed into the gates, which are connected in a manner illustrating binary addition operations.

Adding binary numbers

Diagram showing a logic circuit used for adding binary numbers, consisting of multiple AND and OR gates connected together.

CSS Full adder


				.full-adder:has([data-digit="1"]:checked):has([data-digit="1"]:not(:checked)) .sum1 {
					--on: 1;
				}
				.full-adder:has([data-digit="1"]:checked ~ [data-digit="1"]:checked) {
					--and1: 1;
				}
				
VS Code editor showing CSS code for logic gates, and a visual representation of a full adder binary addition interface with toggleable bits.

CSS Full adder


				.full-adder:has([data-digit="1"]:checked):has([data-digit="1"]:not(:checked)) .sum1 {
					--on: 1;
				}
				.full-adder:has([data-digit="1"]:checked ~ [data-digit="1"]:checked) {
					--and1: 1;
				}
				.full-adder:has([data-digit="2"]:checked):has([data-digit="2"]:not(:checked)) {
					--xor2: 1;
				}
				
Screenshot of a code editor showing CSS for a full adder, with a CSS-powered binary addition interface below illustrating the operation of a full adder with three groups of binary digits and sum display.

Adding binary numbers

Diagram illustrating the process of adding binary numbers using logic gates. The diagram shows three sets of inputs connected to combinations of AND and OR (or XOR) gates, representing the logic required for binary addition.

Adding binary numbers

Diagram showing a digital logic circuit for adding binary numbers, consisting of interconnected AND, OR, and XOR gates arranged to illustrate the process of binary addition.

				.full-adder:has([data-digit="1"]:checked ~ [data-digit="1"]:checked) {
					--and1: 1;
				}
				.full-adder:has([data-digit="2"]:checked):has([data-digit="2"]:not(:checked)) {
					--xor2: 1;
				}
				

CSS Full adder

Screenshot of a code editor showing CSS code for a full adder logic using custom properties and the :has() selector. Below the code block is a black section titled "CSS Full adder" with a visual interactive interface simulating binary addition with input and output bits represented by boxes and circles.

				.full-adder:has([data-digit="2"]:checked):has([data-digit="2"]:not(:checked)) {
					--xor2: 1;
				}
				.full-adder .sum2 {
					--on: calc(var(--));
				}
				

CSS Full adder

Screenshot of a code editor (CodePen) showing CSS code for a full adder, with a visual representation of a CSS Full adder circuit including binary input and output boxes.

				.full-adder:has([data-digit="2"]:checked):has([data-digit="2"]:not(:checked)) {
					--xor2: 1;
				}
				.full-adder .sum2 {
					--on: calc(mod(var(--and1, 0) + var(--xor2, 0), 2));
				}
				

CSS Full adder

Screenshot of a code editor showing CSS code for a full adder, with a visual simulation of binary addition using colored boxes representing input and output values.

Adding binary numbers

Diagram illustrating the logic gate circuit for adding binary numbers, showing multiple AND and OR gates with their connections representing how binary inputs are processed to produce summed outputs.

				.full-adder .sum2 {
					--on: calc(mod(var(--and1, 0) + var(--xor2, 0), 2));
				}
				.full-adder:has([data-digit="2"]:checked ~ [data-digit="2"]:checked) {
					--and2: 1;
				}
				

CSS Full adder

Screenshot of the CodePen editor showing CSS code for a digital logic "full adder" component. Below the code, there is a visual simulation of binary addition, with boxes labeled 0 and 1, demonstrating input and output values for the adder circuit.

				.full-adder:has([data-digit="2"]:checked ~ [data-digit="2"]:checked) {
					--and2: 1;
				}
				.full-adder .carry {
					--and3: calc(var(--and1, 0) * var(--xor1));
					--on: calc(var(--and2, 0) + var(--and3, 0));
				}
				

CSS Full adder

Screenshot of a code editor displaying CSS code for a digital full adder logic gate, with a UI demonstration below showing binary input and output values for addition and carry.

				.full-adder:has([data-digit="2"]:checked ~ [data-digit="2"]:checked) {
					--and2: 1;
				}
				.full-adder .carry {
					--and3: calc(var(--and1, 0) * var(--xor2));
					--on: calc(var(--and2, 0) + var(--and3, 0));
				}
				

CSS Full adder

Screenshot of a code editor showing CSS code for a full adder, and a visual CSS full adder demo interface with labeled inputs and outputs displaying binary numbers.

Adding binary numbers

Diagram illustrating the logic gate circuit for adding binary numbers, showing a cascading arrangement of AND, XOR, and OR gates representing a multi-bit binary adder.

				.full-adder:has([data-digit="2"]:checked ~ [data-digit="2"]:checked) {
					--and2: 1;
				}
				.full-adder .carry {
					--and3: calc(var(--and1, 0) * var(--xor2));
					--on: calc(var(--and2, 0) + var(--and3, 0));
				}
				

CSS Full adder

Screenshot of a code editor showing CSS code for a full adder, with a visual diagram below representing the addition of binary digits (1 + 0 + 1) and the resulting carry and sum outputs using colored indicator circles.

CSS Five Digits Addition

Screenshot showing a live web demo of binary addition and subtraction using five digits. Three groups of five binary digits are displayed in colored blocks, with two groups being added and one subtracted, demonstrating the result visually with colored highlights for each digit.

CSS Five Digits Addition

<div class="full-adder">
					<input type="checkbox" data-digit="5">
					<input type="checkbox" data-digit="4">
					<input type="checkbox" data-digit="3">
					<input type="checkbox" data-digit="2">
					<input type="checkbox" data-digit="1">
				</p>
					<input type="checkbox" data-digit="5">
					<input type="checkbox" data-digit="4">
					<input type="checkbox" data-digit="3">
					<input type="checkbox" data-digit="2">
					<input type="checkbox" data-digit="1">
				</p>
					<output class="carry"></output>
				</div>
				
Screenshot of a code editor displaying HTML for a CSS-based five-digit adder, with a live preview on the right showing five digit boxes—some activated in green, some inactive in gray—representing binary input.

CSS Five Digits Addition

Screenshot of a CodePen interface showing CSS code for a full-adder implementation on the left, and a visual representation of five binary digits (with three middle digits highlighted) on the right.

Let's close the gates...

Is CSS a programing language?

Let's close the gates...

  • Is CSS a programing language? YES!
  • Can we build a computer with CSS? YES!
  • Do you think CSS is way cooler now? YES!

Thanks for listening

https://AmitSh.com/links/cssday2025/

Illustration of a large yellow smiley face above the text.
  • CSS Animations
  • CSS Keyframes
  • Logic Gates
  • NOT Gate
  • AND Gate
  • OR Gate
  • NAND Gate
  • NOR Gate
  • XOR Gate
  • XNOR Gate
  • CSS Attribute Selectors
  • HTML Checkbox Input
  • CSS Custom Properties
  • CSS Grid
  • CSS Pseudo-Elements (::after)
  • CSS Background Image
  • CSS :has() Selector
  • CSS :checked Selector
  • Binary Numbers
  • Half Adder Circuit
  • Full Adder Circuit
  • CSS calc() Function
  • CSS Trigonometric Functions
  • CSS Five Digits Addition