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.
- 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
Ever wondered how a computer actually works? What a CPU is actually built of? And if it’s possible to build one using only CSS? If so, this talk is for you. We’ll break down the fundamentals of a CPU and rebuild them entirely in pure CSS. Using clever selectors and advanced styling tricks, we’ll construct working logic gates and even assemble them into a functional calculator. No JavaScript, no magic, just CSS pushing the boundaries of what’s possible.
Sketchnote by Artem Pendiurin
