 Nicole called me on, I think, Tuesday of this week and said, hey, can you be in New York on Friday? And I said, ha, ha, ha, ha, my goodness. Sure, yes, absolutely, I'll make it. And so I'm sleepy, but we're good. We can switch over to my settings pane. I just, let's see, I just tweeted this deck, so you should go get it. That's, I'm at Colin McGill, C-O-L-I-N-M-E-G-I-L-L. And there are lots of examples at the end that we will play with and that you can hack on so that you can see for yourself what this is all about. This, this is, I couldn't, I really could not be more excited to have made it. I'm from Seattle, I'm from a startup called polispol.is and I'm from a shop called Fromitable Labs that builds a lot of walmart.com's critical infrastructure. I don't work on that project, but I work on others, so there's a lot of concentrated web knowledge. I lead teams and I lead teams on really complicated client-side web apps. I'm mostly in JavaScript all day and I, I am obsessed with web-based data visualizations and interactive, interactive data in general. Work with a lot of data scientists, really love, really love shareability, filterability, sortability, and a lot of these, a lot of these patterns are gonna come up. A lot of patterns that I've learned in interactive data visualizations will come up in this talk. So without any further ado, let's, let's, let's do it. Okay, so if I was here to announce that SAS had been integrated into the browser, this would be a much warmer reception. I'm not. But if I were, and if I said, hey, you don't have to compile to static CSS anymore, you can keep your variables and change them at any time, recompute your whole app anytime. You can keep your functions, they can, you can recompute those at any time too. You can keep your modules, don't have to have globals if you don't want to. We would be very excited as Kira Knightley is. But I think it's gonna be more like, it's gonna be more like this. And I don't know, I still, at a gut level, I know that this is the right gift. I still don't know whether I'm the panda or you are the panda. We'll find out during this talk. So we know that CSS, vanilla CSS, is not, is not where it's at, right? That hasn't been hipster since like 2007, right? We've been using, we've been, I started out in vanilla CSS. And then I went to, I then I went to Bootstrap and then I did less, I just like downloaded Bootstrap and used it. Then I went like less with Bootstrap. Then I went like SAS with Bootstrap. Then I like ditch Bootstrap and just use SAS. And then, and then, you know, then I did SAS and CSS and just using line styles. So I mean, I feel like I've been on a similar progression to all of you. I really, it really resonated with me, what Ada Kunlis, I did write that down. Where are you? That was great. Yeah, your talk was great. It really resonated with me. I mean, I feel like we're on a similar journey here back, back to code, right? So, okay. Things have changed since 1998. The ecosystem is way better. We do things differently. Declarative is not an asset anymore. Declarative is a liability. CSS is a liability. And that's really the core of what I'm here to say. And that there are now way better ways to solve things with JS. And the ecosystem has changed in the following ways. In 1998, we had a bunch of HTML files and you had to go through them and you had to change things by hand or script that if you wanted to change styles. It was an appropriate abstraction to have a declarative style sheet. Being able to abstract everything and have variables was helpful, but really the declarative selector-based model came about at a much simpler time in what we were asking the DOM to do and what we were asking the web to do and in terms of what interactivity we were expecting. Now we have play.spotify.com, right? We have Spotify on the web and streaming and overlays and clicking and all sorts of state and multiple-pane music players that we're still asking that same kind of professor web page DOM to give us. We can require things. We have modules. We have NPM. We can share JavaScript. And we have immediate mode UIs. I won't go, we're gonna come back to that. So just remember that word and we'll be back there in a second. CSS is causing problems. The long and short of this is that declarative is not great for interactivity. What we have to do is we have to create classes semantically and then grab them with JavaScript and take them on and off the DOM and you remove the class and you add the class, you remove the class, add the class, you remove the class, add the class. And the more complicated that gets, the more impetus there is to move more logic into CSS and to do effectively more if statements in CSS. But that has diminishing returns because we can't pull all of the logic of our applications into CSS. And now I'm looking at eutomic CSS. The medicine is now worse than the disease because now we're creating these massive, like semantic frameworks to try to handle the complexity of what CSS has become. So if we change state anywhere in our application, we expect styles to be changed. Our bosses say things like, or our clients say things like, hey, okay, so if this user isn't authenticated, don't show that stuff. Or that should be, or this is on this device or an Android doesn't support that. So make sure that you're showing the other thing. Or when you load this, if it loads incorrectly, then this pane needs to change. The conditionals just keep piling on. That's never gonna stop. And so really at the heart of this, we need computation. And that's what this is about. This is about recomputing styles. This is about computed styles. This is about recomputed styles. Every time any data changes in your application, you may need to recompute your entire style sheet in response to that. And that's really what, at the essence, using inline styles is about. So I love D3. I have been using D3 for years. And I was using D3 because I was building interactive data visualizations. At the same time, I was building all of these complex app behaviors that are just in normal CRUD apps. The login, the settings pane, the blah, blah, blah. So what is it? What is it about this that was just so compelling? And I was using these two things side by side. Every time my data changed, and this is an immediate mode UI, every time the data changes, you re-render. So every time my data changed, I got to re-render and I got to pass my markup through this chain of functions and d.foo equals bar so I could check. I could say like, hey, if this, let's say I have 10 circles, and if they're an even number, if it's zero, two, four, six, or eight, then make those red, make the odds blue. I could use load-ash and I could reach in there deep into an object and say, hey, this object has a certain property or key value pair and I want it to look like this because of that. You can do really deep, much deeper than nth child kind of, you can do nth child too in JavaScript but because it's just like check the index of the array. But this was so compelling and I just kind of, it was unconscious though. I had it in the back of my mind and it really wasn't until, it wasn't until I saw React and it wasn't until I saw Christopher Shado talk on CSS in JS that it really popped into my mind where this all was going and where this is all going is that we're gonna keep the styles but we're gonna ditch the cascade and we're gonna ditch the sheets and the reason is that if we recompute the entire application every single time our data changes what we end up with is computation on the client. We end up with this and I can tell you we're building major client applications like this. Once you have functions, it's very hard, it's very hard to contemplate going back. Why can we do this? Compute padding and pass in some state, whatever you want. What, in what circumstance can we do this? Well, we can do this if our inline style is a compile target. If we take an object, put it all together and aim it at a style tag. We can compute every time the application changes and again I'm talking about specifically these examples will all be with React because it's the best example of this right now. You could do all these examples in D3 but that's less specific. It's more specific to SVG than it is to the DOM, React is general. So where you cannot do this is in a class. CSS classes, defining a CSS class does not allow you to do a ternary because it simply won't run. It's not meant for that. And doing this with jQuery is a pain. If you want to do this with listeners or if you want to do this in same thing with event binding in Backbone, if you want to do this you would need to attach an event listener like click or change or on Hover, things like that. And then you would need to change the CSS in response to data changes. And this is a lot of what we've been doing in Backbone. You have a change in a model or you have a change in the data somewhere and that fires off some view method and the view method changes the DOM. And to do, to recompute all of these styles every single time and to only work like this would be really, really belaborous but I'm gonna show you how to do it. In React it's not bad anymore. It's just fine to do this. This solves just about everything about the complexity of mobile responsive web applications which can run into the, how many people here have been in a CSS code base that has more than around or more than 10,000 lines of CSS? Yeah, totally, me too. So the complexity of that and how many of you, for those of you for those of you who raise your hands, how many of you are handling that mostly with naming conventions? Yeah, it's about two thirds of the same people, right? The best thing we have right now is make sure that you're name spacing to your views or make sure that you're using, make sure that you're using naming conventions and make sure that you're using these kind of CSS best practices but it still becomes a mess over time because when you look at a style sheet it's not clear what state may lead to that class being applied to the DOM. It's a small research project to figure that out and that can be very hard to tell whether you're changing someone's code, whether it's going to update the right thing or not. If you're using computation, we're talking computation with properties. If a property changes or if you re-render, you're going back to check some property. You can require a JavaScript module and globals dot border radius small and this is just a big file, right? It's a big object. Just like you would have your SAS variables, you would have a big object of JavaScript variables and it would be get border radius small or dot, you know, sans-serif and you would have all of these variables and you could recompute them, you could change them any time, not just before, not just when you compile. You can do that any time if you're using JavaScript. So computation with functions. You could say, hey, the width should be computed and you could get access to the window. So you can, well, I'm going to show you an example with this in just a moment. There's an example called molten-letting, which is, have you ever seen that? Where you've got like the line height is a function of something else. Hard to do, but not with this. Having a ternary, right? You can check a condition, check a global condition and then set padding. Check the, check a global flag, check a boolean and set a setting. Think SAS, but with access to everything that JS knows and not compiled to a declarative syntax. Not compiled to CSS, not compiled to a declarative language. Compiled, not compiled, just variables. Just in the JavaScript runtime. We would still have modularization and this is what I say when I say the ecosystem has changed. Many of the things we couldn't do with, many of the things we couldn't do before we can do now. We can modularize the same way we do with SAS. We would just modularize, but use objects instead. So let's take a look at some of the edge cases. One of the first immediate objections is, well, okay, but that's not gonna handle hover. That's not gonna handle any of the pseudo elements. And the truth is you can do those with JS event listeners and we built, our shop built radium and there's actually like seven others that have already come out besides radium to handle all of these edge cases and do them with JavaScript event listeners and the performance anecdotally, the performance is blazing fast. There's no issue whatsoever. And like I said, you can do things like, you can use load ash. Has anyone here used load ash or underscore? Great, okay, yeah, great, okay, great. So being able to use load ash and underscore to check the value of an object before you apply padding to it, that's really powerful. It's as expressive as you can imagine. So one of the other problems, of course, is that with CSS, as we have these 10,000 plus line CSS files, a developer recently said in a project I was working on, well, it's like, I have my button and I just need to be in front of everyone else's CSS and just make this wall so that I know that I'm in front of everyone else's globals and it's like, well, that's, that is a problem in a big project. We have all of these globals that are affecting your button. What with this, if you don't apply anything to it, you would end up with an HTML button, a completely unstyled button because everything would be scoped to modules and you would just add things as you needed them. So what does this mean? It means that CSS is pretty over. It's been pretty over for a while and that's why we're using SAS. The suggestion here is that SAS is a kind of coming home to logic but that logic is JavaScript. So that's the, well, now I'm gonna show you, I promise. And I know what you're saying. Because, you know, it's very, it's natural, right? It's natural. This is a radical idea and this is a radical departure. Basically is the, we've been building up a lot of best practices around this language and I'm saying that they're, I'm sorry. It's, there is now a better way and I have, I think this is gonna be a tectonic shift in the way that we build web applications because it's gonna handle state in a way that we have hitherto never been able to contemplate handling state in complex web applications. Do keep in mind that my bent, of course, is coming from really large, complex client-side applications and interactive data visualizations. That's my tool chain. That's what I love. I want it to be really expressive. So, you know, I don't build static e-commerce pages and there's nothing wrong with those but even those, I have to say, many people have switched to SAS. Why? Because you have variables, right? And there's still state there. So, okay, let's look at some examples. So, I'm gonna ask you guys to go ahead and look at these on your computer as well if you have it. I tweeted this link out to the presentation. I'm gonna pop out of here and just show you these. So, let's see. So, the first one is state. So, let me show you what this does. So, I'm gonna type into this and I'm gonna say, this paragraph is blue and this paragraph is 72 pixels and then I'm gonna say this paragraph is pink and I'm gonna say this paragraph is yellow. And so, this is reactive when I'm changing the state of the application. The styles are just recomputing. And you have to make the next thousand jumps to get to your own web application which is, okay, wait a second. What are the states that we have and how do our styles change in response to that and how many times are we duplicating classes to try to create these different states in classes and in sets of names based classes? Right. So, let's take a look at the code that makes this happen. The code that makes this happen. Code that makes this happen looks like this. So, this is react. Okay, hold on. Let's pull this over. So, we have an on change. Oh, God, Adam, come on. Okay. I love you, but, all right. Control zero. Control zero, is that what I want? Control zero, command zero? All right, it's okay. Hold on. There we go. I just, just minus. But that doesn't help you guys today, you can't see it. All right. So, we, anyone seen react before? Fantastic. Okay, well then you're gonna be really excited because this works with what you're already using. So, down here we just define a paragraph and we say this paragraph is this.state.color and this.state.fontsize. So, we're just putting the, we're just putting those variables in there and we're simply setting style to this.state.color, this.state.fontsize. So, this is like the simplest start here. And then we have the input fire function. So, when the inputs fire functions, they set state to target.value and so, they'll set state to yellow and blue and 72 and when we, when we change them and we say pink or we say blue, our styles change reactively or 36, right? Okay, so now, let's take a look at a different one and let's go to, let's go to that molten, molten, molten letting example. So, we start out with an initial line height of 1.5 and a font size of 14. So, what we're gonna do is we have this big paragraph down here and the line height is this.state.lineheight and this.state.lineheight starts out at 1.5 but when component did mount, when it goes into the DOM, we call getlineheight and getlineheight finds the paragraph and then feeds it to get computed style so it finds out how wide it is and then it does set state lineheight parse int divided by 300. So, we are getting the width of the paragraph and then dividing that by 300 and setting that to the value for lineheight. And what that means is that we get dynamically computed and recomputed lineheight every time we change our window. If we scroll, if we make it more expansive, obviously we need more complex math in there to make this actually look good. It's just a simple, this is the simplest possible example but every time, because we have an event listener on our window, every time we move the window down, we recompute our lineheight and we recompute our lineheight. Our lineheight is a function of the width of the paragraph. So, that's the function example as for before. Okay, let's see. Next example is a, let's see. Okay, next example is Ajax. So, this is a little mock API call, font family courier, font size 72, color blue. So, we're gonna take a look at, we're gonna take a look at this. You can see here we have a little slider, once again this set state, so we can just dynamically change our font size and make it zoom up and down. That's a couple lines of code. Not terribly useful but also demonstrates changing state. So, what's really interesting is that we're gonna make an Ajax call, we're gonna make a get to this API endpoint, we're gonna get back some data and then we're going to, we're gonna change the state of our application and we're gonna change the state of the application from the defaults, which are red and like 16 pixels, to what came back in the response. So, if I click Ajax and if the wifi works, there you go. So, when it came back, it set the state of the application. What does this mean? What this means is that if you loaded up a widget in an iframe, take this example. Let's say that you design a widget. Anyone ever been asked to design something that was, that was themeable? And you know, and your boss was like, just make it so that it'll look like whatever page the person, you know, they have their stuff, they have their colors, right? And just, you'll just make it like whatever theirs is. Or so that they can make it whatever like theirs is. And you're like, bill, right? Like that's gonna be, that's gonna be weeks because it is not simple for them. What am I gonna have? I'm gonna have them like load a different style sheet asynchronously. Try this. You have an iframe and you have a bunch of data attributes and you have a script tag and you post message inside the iframe and pass in an object. That's all. So you pass in an object inside of that iframe and you set that to your variables file. So you swap out your variables file for their variables file. All their fonts, all their colors, all their sizes, all their default paddings. And you can just recompute your app while it's in the browser on the fly in response to like a, you know, a post message. That's the idea. Recompute anything, anytime in response to any state. So next example, these are the simpler ones. These are more just for you to get in and play with and hack around. They're in gist, so you can copy this gist. You can find the gist, copy the gist, get it under your desktop and just start hacking with it and playing with it. These are a little bit more complicated but they're also linked to there and these are thanks to Ken Wheeler who helped out with these. This is SVG. This is generating random values and using tween state. So this is React and JavaScript animations to tween these values. So is this. This is a filter list done with tweening. When you filter children, they transition smoothly to their new position and that's pretty hard with CSS but this is in the DOM, this is an SVG or anything. These are DOM elements transitioning to new positions because you can tween, basically what he's doing is he's making a clone of each of these elements and then tweening them, getting the absolute position, getting the absolute position of where they're going, tweening them to that new state and fading in and fading out the correct ones and so you can see that that creates a nice smooth animation. That's a little bit complicated except that it's a React component. What's that mean? Well, you can just take that component, put your children inside of that component and then don't put your children inside of components. Not kind. Just put the children inside of components and then just allow the component to do the magic. So passing these things around inside of a company or just in the open source community in NPM modules, really nice because you don't have to pass around a style sheet for this or you can just pass around a component that happens to do all of its computed styling internally and that's also very powerful in terms of sharing experiences, not just sharing like, hey, I got this to look this way or hey, here's how I did this in my app in these conditions. If you can share a component and that component handles its styling then you can share experiences like this and just allow someone else to pick this right up. And I mean, you could probably get this working in your app in less than an hour and that's pretty powerful for complex behavior. The last thing, this is the CSS website. This is radium handling complex keyframe animations. Oh my goodness, I'm so sorry, I need just a second here because this is, I think I'm gonna have to go full screen and then go to editor, go to presentation. No. Whose site is this? Oh, you know it, sorry. Okay, full page. Okay, so this is radium, this is JavaScript. This is an iframe inside of a div which is animating with keyframe animations and radium. This is all JavaScript animations and you can see the responsive, this is the actual site so it's responsively, you can see we can click on something in here and see that it actually works. That's the, yeah, so anyway, so let me come out of this. So I wanted to end with 15 minutes because I figured there actually would be a lot of questions. I know, they told me not to take questions but I just, I want to, so. So I'm sorry, Nicole. Who do you think you are? So I am happy to answer any questions. Anybody want to go? Yeah, we are not shipping any CSS. I think though that there is a place for CSS. In radium, for instance, you can define a scope style tag and put like a CSS animation in there. I think there are some, I think that the amount of CSS that would be useful would fit inside of a style tag in the head of like an HTML template that's an entry point to your whole app. Things like styling normalize or styling body, things like that I think are, or if you are, you could certainly style body with, but if you have, if you do want every paragraph to look a certain way, there's no reason not to use globals but globals are maybe, they may be appropriate for, I'm thinking probably less than 5% of what you'll do with this will be actually in CSS itself and the rest will be scoped to the elements themselves so that you can recompute anytime you want. Yeah, sure, sure. Yeah, I think that one of the great, one of the, one of a really good reason to make this shift would be that you could take that button, that button would own, and I'm talking about React, but just in general Angular's doing a full rewrite and their DOM model is gonna look a lot like React. So this is the direction of things. I think being able to share a behavior, if you write a button and it's a great button, it has a wonderful little spinner and it has all of its CSS, all of its styles, shoot, all of its styles contained inside of itself, then you could put that button on NPM and have, or a private NPM and have your coworkers download that button. Here's another example of why you might wanna do this. So if you are in component playground, so one of the things that our shop put out was this thing called component playground, and component playground, it's gonna take a second to load. So this is dynamically generated, so I'm sorry, it's like dynamically, this is all computed, this is React, so if you say min width, min width is 400, so you can change the button and you can have a style guide for your company that is not only a style sheet with static things, but you can have a style sheet with behaviors. So even that button might hover or change in different states or have a loading state with a spinner. You could bundle that spinner logic up inside of that button and just ship that as a component and then have all of that scoped to a single NPM install, NPM install button, or NPM install our pivotal dash, style's dash button, and then you would just require pivotal dash, style's dash button and then it would just load that up. And you would pass in whatever you wanted to in props or not and it would have default behaviors that could be overridden, but even in buttons. I mean, take a look at, even for a button, for now in a web application, like take Twitter, let's see. Look at this, I mean, when you click here, this button has a state, and it has, but this button has state related to that form field and so even the lowly button in web applications can be quite complicated given loading and given permissions, whether it should be there or not. A single button, if you're not logged in, won't be there. If you haven't typed anything, it's gray. If it's gone over too long, then it's gray again. So I think there really is, everywhere you look, you find state now and I think that's my primary motivation for all of this. Yeah. Say again, why can you ship CSS files? Oh, why can't you? Nothing to stop you from doing that. Yeah, yeah, you can. If you're sharing a style sheet, how would you share state? Right, but if you then need jQuery or other JavaScript to add and remove classes, given different application state, that's where that breaks down because you end up with a style sheet that has states that are implicit but not explicit. It's not explicit when one of these style sheets would be applied or not. If I handed you a component and everything in that component is logic, then you can see when that will be and when that will not be applied. If I hand you a style sheet and no JavaScript that puts the styles into and out of the DOM, you can see what's going on. Yeah, yeah, but if you do that, that's back to one of my earlier slides. If you do that, you lose, you can't do this. You cannot do computation and that's what I'm after. I'm after computation. Was that, or you put two parens after foo like I did in the other examples and then pass an argument into it and then have a module that checks 18 other things, makes six API calls and then comes back. That's computation. So I mean, it's a simplified example but you cannot do that in a CSS file. So putting this class on something in a React element and then having an external style sheet does not solve the computation problem. That's at the core of this. Yeah, go ahead. Yep, great question. So with React, you can do server-side rendering of a web application so you can bootstrap the data you need, put everything into a single string, no classes, no CSS, just put everything into HTML and ship it over and it'll be workable. And then you can have the clicks go back to the server and load another page. So this would all work without, this would all work with just server-side rendering as well, go ahead. Yeah, they do, they do. So JavaScript's gotten way faster in the browser. We've been, some of the stuff that I showed you, we've been working with the examples of the transitions, tweening, tweening tens of things on the page, performant, adding lots of listeners, performant. We haven't hit a lot of barriers. Some of our initial tests suggest that looping over the DOM with very complex CSS selectors can get very slow, whereas when you're styling the element in particular, that's going to be faster. So we, because the styles are applied directly to the element, but we do not have, I would be lying to you if I told you that the perf story is completely nailed down on this. This is really new and we don't have, we don't know in which cases it's going to be vastly better or vastly worse. I, we have not run into any issues and we're shipping this on big stuff, so. I'm not concerned, yeah, sure. So in this case, you might have, do you use SAS now? So do you have a variables.scss file? No different. So you would have an object and you would do module.exports, module.exports equals globals, and you would have var globals equals in a big object of all of your colors and stuff like that, and then in your component, you would just do require globals and then just refer to that global. So you can, you don't need to necessarily, sorry about that, you don't need to necessarily, I was just gonna eat the microphone because I'm really hungry. You don't need to, you don't need to reference something inside of the component just because you're doing inline styles. Your styles can be distributed in whatever modular way you want them to be and they can be, there can be many smaller objects, which are running JavaScript onto compute larger objects. So there's no, you know, even in that globals file you could reference other files there that have logic, that for instance maybe you want that globals file, that global variable file to be, maybe you want your default padding to be, or your default paragraph padding to be a function of whether, of your device. So, or your width. So in that case you would just use the, you would use computation there to check device or width and then compute what your globals are and then reference the globals in the component itself. Does that make sense? SAS is correct, but SAS compiling to CSS is wrong.