Build Custom Interfaces Using CSS Open Props
with Adam Argyle
Learn how to make a great-looking interface (+ animation!) with ready-to-use CSS variables from Open Props. Open Props is a design system for any tooling. Adam Argyle will teach us how it works.
Topics
Resources & Links
- https://twitter.com/argyleink
- https://lwj.dev/
- https://open-props.style/
- https://www.learnwithjason.dev/api/schedule
- https://www.learnwithjason.dev/styling-with-attribute-selectors
- https://codepen.io/argyleink/pen/RwxJKQa/2256560bf93a131b58b5774e840d51f0
- https://codepen.io/argyleink/pen/gOXbvjj
- https://discord.com/invite/AqA4fU886r
- https://twitter.com/openprops
- https://stackblitz.com/edit/jit-open-props?file=index.css
- https://www.learnwithjason.dev/schedule
Transcript
Captions provided by White Coat Captioning (https://whitecoatcaptioning.com/). Communication Access Realtime Translation (CART) is provided in order to facilitate communication accessibility and may not be a totally verbatim record of the proceedings.
Jason: Hello, everyone and welcome to another episode of Learn With Jason. Today on the show, we are bringing in Adam Argyle. How are you doing?
Adam: I am swell. How are you?
Jason: Doing great. This is going to be a fun one. We were talking about how we have been in each other's Twitter orbit forever and never spoken until this happy accident of you sending me a message about open source. -- Open Props. Want to give us background on what you do?
Adam: Been in the industry for many years. Design managing and all sorts of stuff but the thing I love is making good UI because it is hard and when it is done well -- the better I do my job as UX engineer, the more gorgeous and buttery of an interface I pluck the less someone respects my technical job. They are like this carousel is so easy to use it must be easy and I am like damn it. I made it so easy and people think my work isn't good. No, anyway, that's me complaining. But I love the UI space and making interfaces. I work at Google CSS for the Chrome team. I love watching the specs and helping and I build stuff every day. I am on the ground and go back to Chrome and I'm like some of this stuff is hard and I go back to the ground and try to keep a healthy cycle of how to keep updating things and making it easier for people to build stuff and yeah, that's a decent short rap.
Jason: Yeah, yeah, selfishly I was excited when you reached out because one of my favorite things as anybody who has watched more than a few episodes of this show will know is I love CSS. It is so much fun for me to get in and build things and twerking the way they look and feel. It is often something I will get so into in a show that I will forget to do the rest of the show. I am exciting what we are doing and I think it will be beneficial to spend a lot of time on it. You are working on something I find interesting called Open Props. Open Props is -- let me take a crack at this ask you can correct my take. -- and you can. Open Props is kind of like tail wind if you just wanted to use the platform.
Adam: So you are on to something there Kell is why on the home page of Open Props it says subatomic -- which -- we have tailwind which is the subatomic system and you use them via the class and the class can encapsulate many things. Open Props is taking the ethos of a pre-made design system and instead of delivering it as classes it delivers as many things as it can as simple static prompts. You get there composability in a new way at the value level as opposed to the class level so you could go build your own atomic style sheet out of Open Props but, yeah, thinking about them in atoms along the lines of tailwind is a good way to think about it. Tailwind still has some clear advantages. Being a utility style sheet is a great way to go and you can kind of merge them if you like.
Jason: OK. Here is what I saw that I thought was cool because in my typical fashion I did zero research here before we started the show.
Adam: Rad.
Jason: But I looked at the home page for a few minutes and what I saw that I got excited about is all I have to do to use Open Props is add an @ import in my style sheet. I don't need a build system or to really use any compilers. I just get to say, OK, I want to use this and now I use CSS variables. So I do like the var-dash-dash and get one of these properties and it just works. I find that very encouraging because that was the magic of like when you used to use something like say Bootstrap where it was this sort of magical like once I have started now I can put whatever I want and it just works. Like I don't need any complicated things. I don't have to figure out how to hook my CSS into my JavaScript and into the HTML. I can just write code the way I know how into the browser and this should allow us to prototype in the browser but the other cool thing about this is it sounds like, if I am understanding correctly, we can also plug it into any build system really easily. Today I know we were going to use next.js so we can show you can use this wherever you want. You can do it in plain HTML but you can also take it into your complicated build system and it is just going to work.
Adam: Excellent recaps. Fits in with CSS modules, fits in with SaaS. It has many levels of usage. The most basic usage is pop in the CDN import. No NPM. Just grab the prompts and go. It can be that simple. If you want to NPM install it you can pull it in with nice exports. If you don't like typing out the whole URL you can type import Open Props and that's another fun thing about Open Props. Everything is searched as an individual file -- served -- so if you want just the colors, the gradient own the animation you should import the easing. You can grab and go a lot or a little. You can CDN and NPM and if you want to go to the advanced mode if you are worried about performance and not shipping prompts you don't use you can use this plugin that are created called Git prompts, just in time prompts. What you do is set-up the plugin to have this pool of properties so it is sitting there in memory and as you use them, just like tailwind, the prompts with put in the style sheet only shipping the prompts you used at build time. It is pretty cool.
Jason: That is very cool. It sounds like it will please the folks who are always worried about bloat in projects which is one of the things that I think is really hard. You don't think about this as you building. You need to solve a problem so you start solving that problem and when you get to the end if you don't consciously sit down and audit the amount of code you are shipping to the browser you can accidently be over fetching data or shipping an entire library you are using 1% of. You can be doing all these things and some of that gets automatically handled but typically it is the thing you have to do a manual clean up so I love this is built in. I can only ship what I use and it will automatically work and I am just going about my business and I don't have to schedule a separate sprint or work cycle around performance review for Open Props. That's really nice. Is this a project that you built yourself? Is this coming out of a team? Where did Open Props come from?
Adam: This came from myself as I continued investing in custom properties and building and implementing design systems. At Google five years ago I was on the Google Cloud deem on the design system teams and there was tons of us. I have been really deep into design system land for a long time, looking at the consistency and inconsistencies coming out of those and Open Props was born out of two things. First was a lot of my own stuff was coming along with me whether it was custom properties and we have one that will be rounded unless it is full width and then it goes squares. It is a corner radius that automatically adjust and it is a trick someone made. I was noticing superpowers can get baked in a prompts and you give them a rad name, give the trick a meaningful name, and I was acquiring those overtime and the thing where it hits home for me is most design systems are thinking bigger than the web which is great. They output colors for, you know, every platform, Android, iOS and web. The bummer is whenever they shift the web colors they are probably a hex color and hex is fine but I don't know how much you know about the color theories coming out but it is not going to be good enough soon.
Jason: HSL, or HSB is that what is coming?
Adam: Have me on for another color show. This would be fun. HSL, RBG, HWB, hex 4 and hex 8 codes are all within the same color space of SRBG which was the typical monitors we have had for 30-40 years. Think back to when we had only 256 colors on the web. We are stuck at 256 million now but every display most people have -- I need more colors -- but every display people have in their pocket, the one you are probably looking at is probably a high definition display and it has the capabilities for these vibrant colors and richer blacks and stuff like that. You are picking colors from the low common denominator color space and in the future that's already shipped in safari you can access the colors that do reach in the better display. In order to get that, though, you have to be conscious of color spaces and be thinking about color that way. When I was making Open Props I wanted it to be CSS centric. Not multi-platform. This is where this design system is unique. It is webby to the core. It uses web units like rims and characters that don't transport to other places in the web. The box shadows are very specifically created like stuff like that. The gradients don't port to other platforms. All this stuff is made for web as small as it can be and tucked behind a well named prop so that's the other idea. I wanted a web design system to use. Not one trying to fulfill a bunch of stuff I didn't have.
Jason: Right. That's super cool. Now I am like I want to learn more about color. We will do that on another show but today we are doing CSS. I have a proposal for you. I have a proposal for how to name -- earlier you said conditional prompts and I feel strongly you should rename that to swappy prompts. It is fun to say.
Dropping swappy prompts. I can't even say it fast.
Jason: Who is making music out there? Dropping swappy prompts. Somebody remix that.
Adam: Definitely asking for it.
Jason: What else should people know about Open Props before we move over into building something with it?
Adam: One is people are like I already have a design system and I don't need yours. But do you have easing? Animations? How rich are your shadows? Are they adaptive to light and dark? If the answer is no all you have to do is import one of the prop packs. I called it prop packs.
If you call now you will get four bonus prop pack for the price of one. I need to do like hearthstone and open up the pack and it explodes in your face.
Jason: I think that's great, though. You bring up a really great point. I think every company I have ever worked at and many companies I have worked with people who are there, they are always working on some sort of central design system where they are trying to solve a set of problems and the central problem they are trying to solve is we want things to feel good and feel ours but the vast majority of these teams have one person or two people who really have the bandwidth to focus on a design system and there are a lot of business needs that span the whole company. You just don't have time to do all of those things. So the way you phrase that is you can use Open Props as a way to poly fill your design system and if you do get around to doing your own gradients, great, drop it out but if you don't have time keep them. It gives you that support. It is predictable while you get around to building your own custom version. And stuff you just never need to care about like a border radius swappy prop is not a thing you need to build in house. If it goes full width, don't round the corners, I love that. Don't make me build that. Just make it work. I like thinking about it as you not just use it all or none but a supplement to the work you are doing in-house and because of the post-CSS plugin you are only bringing in the pieces you need to polyfill. That feels like an easy win for teams on design systems to just get a lot of extra bandwidth to get you out the door so you don't have to build the whole thing at once and then hope everybody uses it. You can tackle the real problems, use polyfills and get buy-in and build out the things that really matter.
Adam: 100%. Excellent recap. Item two, other than picking and choosing tiny or a lot of prompts and various ways to consume them, it offers a normalized and a buttons CSS file and I am working on an input file. In addition to you importing the prompts, let's say you are starting a new project like we are going to do today kind of, I will pull in Open Props normalize, this is the CSS developer from Google Chrome and hopefully it is well thought out normalized. I think it is. By bringing that in, it uses the prompts to create a normalized style sheet and then you can import the buttons. It is like three imports. Adaptive normalized so it comes with light and dark, and all the buttons come with light and dark, and you sort of get setup into this like -- and the buttons are awesome. You just use the tag no class name. So if you add a type on to it changes the way it looks. So it can really springboard you there if you are looking to start something new and are OK adopting some of the styles I have chosen. Open Props gets opinionated as soon as you import the normalize but there is cool things you can get there. There is like a prong where you are either adopting the prompts because you want to go rogue and do your own thing and feel free or you can get normalized and start from this base and the base comes with some cool things and we will talk about it but yeah, text classes and surface classes that come with these excellent pairings for you. Anyway, we will get into it.
Jason: Got some fans in the chat. Brian is explicitly calling out your design philosophy which I think is a good segue. Anything else you want to cover?
Adam: No, let's dig in and build some prompts.
Jason: I am going take us to the screen. Let me pull it up and this show like all are being live captioned. Those today are being provided by Maggie at White Coat Captioning. Thank you so much Maggie and that's made possible through the support of our sponsors Netlify, New Relic, and NX, and others kicking in to make this more accessible and keeping the lights on which I really appreciate. We are talking to Adam who is at Argyle Ink on Twitter. You can go over there and give it a follow. Let me drop the link for anybody who wants captions as well. We are talking about Open Props. Is it openprompts.style? OK. Here is the Open Props website. We have reached the end of my knowledge about Open Props. So what's the first thing I should do here?
Adam: Let's kickoff a new Nex project.
Jason: I am going to do an npm -- oh, I did something wrong. I am going to the next doc. Getting started we have got create next app. We are going to create next app and the project is going to be named Open Props.
Adam: Swappy P. Did you ever see that video from SNL? Point pleasant police department?
Jason: Point pleasant police department. Can't even say that slow.
Adam: They are eating muffins and talking with drinks and using a bunch of Ps and spitting on each other and I keep thinking about that with prompts. I don't know.
Jason: OK. We have project here. We will pop it open and so we will get, you know, this is the standard setup but we are not going to do any of that today. We will just -- I am just going --
Adam: While that's there, leave it there. It will make a good example.
Jason: Cool. Let me start the thing up.
Adam: N PM install Open Props is the next step unless you want to use the CDN. I don't know if you have a preference.
Jason: Let's start with a CDN and then we will swap it out. Here is our basic setup here.
Adam: Looking rad. OK. Go to the Open Props site and if you scroll down you will find the CDN import. You will see it is down there. Just grab that one, yeah. Good old unpackage.
Jason: And let's see. Go to styles, globals, throw it right up at the top.
Adam: Throw it in there. Now we have the prompts and nothing changes. These don't do anything. That's one of the weird things about Open Props. I stalled the project and it doesn't do anything. It is just values. Why would you ship just values? That's weird. OK. Whatever. You have the values and nothing has changed yet. Let's make a change. We will add a new line underneath the import. You can pretty much paste the whole thing you have. This time we will add an import for normalize. After Open Props we will do/normalize.mim.css and hit save and then we will see some changes. Now let's go delete all the styles, all the HTML and body stuff. It comes with normalize so you can go back and see we have a dark theme. Even though you haven't deployed something that's what normalize does. It creates a healthy set of browser styles and also puts in, using Open Props, a couple colors so you can have a light and a dark theme.
Jason: If I go to light mode, there it is, and then I can go to light mode and OK. This is coming out of Open Props.
Adam: Yeah, that's the background color I set. It is not quite white. It is like a light gray. Same thing with the background.
Jason: I will keep it up off screen so we can toggle between light and dark mode as we go.
Adam: Notice the link color. That's set from Open Props using indigo5.
Jason: Which is great because that's one of my beefs about a next.js style is they are masked and you can't see it is a link. Immediately I would say this design just got more accessible which is wonderful.
Adam: Good.
Jason: What should we do next?
Adam: Just for funsies, import the buttons. Buttons.mim. And go put a button in there somewhere. Just for fun. I want to see what these buttons look like. How easy is it?
Jason: I am going to go in here and clear things out because I want us to have a blank slate because I think you had a good idea I want to mess with. To start we will do a div and drop in a button making it a type submit or no, a type button because it isn't in a form.
Adam: It was cool. You could do that. There is your button. You can click. Oh, yeah, it has got keyboard support and the whole nine. Hit space bar on there and you will see it. Do you have reduced motion turned on? That should animate but it doesn't if you have reduced motion.
Jason: Accessibility?
Adam: You don't have it on. Is it animating for you or is it instant?
Jaws Jason: The shadow is but the focus didn't.
Adam: I will have to check that out. That will be something --
Jason: I am also on Edge.
Adam: I don't think that should matter. I just shrink if it down. You have the prompts and normalize in the buttons and you sort of setup -- we were going to build like a dashboard here, right? So --
Jason: Sorry. I am jumping ahead because I want to make sure we have time to style it out and I get pigeonholed on CSS. Dashboard showing, pass and upcoming JS nodes. What we are going to do in here is we want to -- let's do like a dashboard, right? We have got all that. And then what I am going to do is I am going to start by just making up our function get static prompts and that is going to be async and I am going to fetch -- wow. What is happening. I have an API out here. It is going to be API schedule. This is how if anybody is interested, I have got the Learn With Jason scheduler and we are going to fetch that. Then we will check if anything happened and if it did we will console log.
Adam: Oopsies. Then we can return and we want all this data -- what do and don't we need? We might need -- let's just keep it for now. And we will be able to send back the schedule. All right. So then what we will get is in here, we will get the schedule. And I want to put together a -- let's go with a new function. We will call this episode card. Now I am just going to -- actually, we will just dump it in all for now. This function, for now, is just going to return a pre that will do a JSON string of whatever we passed in.
Adam: Show me stuff. I want to see stuff is what you are saying.
Jason: Down here we will drop the button. I am going to say schedule.map and we will call it episode and we will return episode card with the episode of episode.
Adam: Yeah!
Jason: I think that was the extra piece. What's missing? Map, map, map. What's it not happy about? Key -- ha. Key = episode.id. I did need the ID after all. Now what we should see on the home page here is -- cannot read properties of undefined because why? What don't you like? Let me try refreshing. Maybe it just needed -- there it is. Here is our dump. As you can see, the width of these got blown out with the pre so I am not going to worry about that because that's not really what we care about but this is kind of like a basic layout of episodes. We are pulling in the schedule, putting it on a dashboard and at this point what we would need to do is actually pull these pieces out, so maybe what we can do to get a better view of what's going on -- that's terrible. I don't want that at all. Let's look at the inspector. We can see -- whoops. Do we get a request? Oh, it all happens in --
Adam: Yeah.
Jason: It all happens in the next stuff. OK. Fine. Overflow. X scroll.
Adam: Pretext is annoying. That white space will get you. Get out of here!
Jason: Before we forget.
Adam: Nice. Yup, got to maximize the width there.
Jason: There we go. We get a maximum size thing and we can schedule. I want to show like the title, the date, and maybe the guest. Maybe that's the thing we want to --
Adam: Sounds like we should make a cart.
Jason: I want the title, the date and the guest and what I am going to do down here is spread episodes so we don't have to double the structure.
Adam: Oh, yeah, superpower. I love that one.
Jason: In here we can do a title make guest and much simpler. We have a nice setup and I am ready to make a card. To make a card, I think we can start this in parallel and we will swap the pre out when we get there.
Adam: Nice.
Jason: My instinct would be to do a class name of card and inside of it I want -- how do we want to display this? We want it to be tabularish.
Adam: There was the list version.
Jason: A list of things that would all be next to each other. What is semantically meaningful?
Adam: You can just do divs and smash them all together.
Jason: We will do the title. We can do another -- let's do the date first and the last one we are going to do is going to be the guest. Let's do the image. We will put in the guest.guest -- whoops. Guest image.asset.url and then we will set an alt of the guest0-name.
Adam: Nice.
Jason: And finally we will do probably for the sake of being able to do layout we will do guest0 name.
Adam: There is a date element you could put your date into it. Semantic choice there.
Jason: What is it? Date time?
Adam: Just date. It is an element type.
Jason: Don't you have to give it a date time or just straight up drop a date in?
Adam: You just drop it in. It will not format it but it is a semantic element for holding dates.
Jason: And if we wanted to we could do a new date and two locale date string and we get -- I don't love that but it will be fine. Or actually we can use 2iso that will be better. 2 iso string. Boo! We will keep locale. It is fine. Then what I want to do is we want to kind of flex this out and make it look nice because I would like for these to be a list. I am going to drop the pre-tags out so that we have -- right. Here is our ability to kind of list these episodes.
Adam: Excellent. CSS modules time.
Jason: Let's do it.
Adam: There is a home module already in the project?
Jason: Oh, you mean this piece? What if we delete all this?
Adam: And just add the new card class in there.
Jason: Let's keep the container. OK. We have a container. Our container gives us a little padding.
Adam: Let's take that padding to rim and change it to padding inline and we will use var size 5. Yup. You just used your first prop. If you don't like that you can make it size 6 and go up a little more. You know? And if you wanted, you can change it to size-fluid 6 or 5 or something like that. Pick an amount of fluid. Yeah. Now as the browser resizes that would grow and shrink appropriately.
Jason: Oh, really?
Adam: There it goes. Nice. We used 5 or 6. That means it has a big base that is the minimum it will be and it will climb to a maximum so easy to use fluid variables in there.
Jason: And inline is to account for right and left?
Adam: Yeah, you can be more precise this way which is kind of nice.
Jason: OK. Card.
Adam: There is no layout prompts and something like a utility class would be much better. Display flex should get them lined up horizontally.
Jason: And because we are doing it the nex.js way I need to take this and import it in here and do card instead.
Adam: Yeah! Let's turn this into a row where it looks more like a padded, you know, kind of item. We will say background; var surface 2. These come with the normalized so since this one -- there is a concept of surfaces in the normalized file so you can put things in front of each other very much like looking at Gmail or design systems there is a concept of surfaces and backgrounds. So there is also text colors, text 1 and 2, and surfaces 1-4. Let's add padding and do a var size 2 and a space var size 4. So a little padding on the top and bottom but more on the right and left. Let's put a gap and do gap size 3 or 4 or something. That's gap 4 in between our items. I was thinking about gap this way. We will get that one in the container. Get the container display grid in a gap. I just felt really bossy right there.
Jason: All good. This is what I am here for. One of those? No, what have I done?
Adam: Let's see. Display... oh, I think it is because we an extra wrapper around the div?
Jason: I can drop this out. It doesn't need to be there because we aren't doing extra bits but something is not liking --
Adam: Oh, the container is wrapping the head so I think there is an extra element and we should put it on the main.
Jason: I am just going to do one of these. Let's do a div class name. Install cable. Then we will come in here and do a table and then I will drag these pieces right on down. There we go.
Adam: Let's give it a rounded corner. Do a border radius var I think it is border radius 2 or 3 or you can pick a different size. There is also a way to get auto complete in VS code so we have instructions on the home page to get that setup but it has been kind of finically recently.
Jason: I screwed something up.
Adam: It is called radius 2. Sorry. That was my bad. It a nice subtle one. Bump it up until you are happy. Go to the Open Props site real quick and then at the bottom there should be a sticky nav which is kind of cut off in my view and there is a button there for borders. Or like a link? There you go. Here is all of the docs for the borders and naming. We were using radius 1-6. Any time we are curious about the syntax, pop in there and scroll to the bottom.
Jason: We will move it to the point where we can see what's going on with it. Make this bigger and this shorter and then we will take this, put this like this, and now -- we have ourselves a super dev environment. I have got my borders which I will click on again. Borders. So we have border size, radius, radius round, and in round I assume makes it circular?
Adam: That's an interesting one. It adds a value that's so large that it guarantees a maximum amount of rounding and yeah, it can be great for the Avatar image where you set aspect ratio to ratio box so there is a prop for making something a box and you can set the border radius to round.
Jason: Radius round. And you said the aspect ratio, sorry, was just --
Adam: Var ratio box. It equates to 1.
Jason: Got it.
Adam: See, look at that. The prompts are working.
Jason: I also want to make these the same size.
Adam: There are size helpers. This is a fun conversation topic in that there is generic sizes but notice how there is size content and size header. You can do size content 1 and that will be like a healthy like this is content I want to be seen and it will be the smallest one there. It is interesting it is varied. Oh, it looks like --
Jason: I think this might be a flex problem.
Adam: It is trying to adapt. We need to set the card image to 0. Is that image a direct child of the card or is there a parent class?
Jason: It's not.
Adam: We probably need to do like card -- what did we put in there?
Jason: It is here. We can do class name; we will go styles -- and then in here we can do guest and we will do a shrink or a flex shrink 0. There we go. These are still pretty big. I feel like those ones I want to call it like 50 pixels, 40 pixels, so it is kind of inline.
Adam: Do size content 6 or something like that. Or not size content 6. Just size 6. The content ones are for pair graphs or images. Just keep bumping it until you are happy. You are in the design system and just playing with the values allowed. Instead of the world is your oyster you have a nice, constrained world to work inside of.
Jason: With another display flex and we will do a gap of -- were we using size before for gaps?
Adam: Size 3 or 4? Oh, yeah, got to put flex shrink0. That is an alignment issue so instead of doing it on the image go back to guest and give it a line items start. Right now the items are being stretched vertically and we will say stop doing that. You can say line items center in fact and it will probably be more aligned with our layout here.
Jason: Yeah. This is coming together.
Adam: We have stuff. It is working. We can put a line item center on our whole row too.
Jason: Beautiful. Beautiful.
Adam: Let's add a box shadow to this card row item. If you want you can check the docs. There will be a link down there for shadows. Yup.
Jason: This is delightful. Shadows. Just grab this little buddy.
Adam: That will be a really subtle one. Try shadow 3. Little better, right? Try 6 for funsies. I can see the huge ones. They are really like a multilayered and can give you a good sense of depth. If you switch to light, you will see the shadows change too which is kind of fun. They adapt their strength to match sort of the new context that they are in so they are adaptive shadows. Little bit more subtle.
Jason: Oh, nice. Yeah. Cool. OK. Yeah, we are cooking with gas here. This is fun. All right. So I can get to like -- a 3? A 4? Yeah. Yeah. Nice.
Adam: Those are fun to play with and really easy to adjust later and you are like I will just drop a number. Open Props went with naming system that as you want to play and prototype you are incrementing or decorating the numbers within the design system range provided for you.
Jason: And like this is really cool how quickly this happens because, you know, this is the sort of thing if I was doing this, I can do all these things with straight CSS, but what happened here is now that these things are named as prompts, when I am being responsible, I associate setup projects with named prompts and go through and make sure I am doing the work to use them but as I am working I forget I setup prompts on this page and I will start doing a whole new set over here and then at the end of the project, I have made this wandering mess. What I like about this is it creates a uniform set of prompts but I am not fully into the like defining a whole design system in a JavaScript config object that gets exported into the prompts and overrides defaults. This just makes sense; right? And I do really like that. I like that this, you know, we have got -- actually just going to give this like padding all of the way around. Yeah. OK. But like we have got this clean setup here. This is a really nice looking way to deal with this setup and I didn't have to think about it hard and the speed with which I am able to dive around in here and try stuff is really pleasant.
Adam: Reminds me of a topic I would like to mention which is Open Props ships all the prompts and the normalize using the ware selector and this is valuable because you as an author import all this stuff and it comes in with zero specificity so overriding the prompts or styles from the normalize is a zero specificity battle. You add it and you win and you will never compete with my library which is kind of cool.
Jason: This is the sort of stuff that is so subtle but it is such a trip up. I am thinking back to when I used to build a lot with Bootstrap and 99.9% of the time it was easy and then you would find this one spot where specificity was high and suddenly you are doing the element name and a class name and an attribute selector with like a style override to get this thing to actually show up and it is like why?
Adam: It is like a specificity war. That's not a fun scenario to be in.
Jason: This is really cool. Getting a lot of love from this in the chat. You know what I want to see next, we will not actually hook it up to data but let's make a form as if I was going to submit a new episode. Let's build out like a title, date, and guest selector.
Adam: Nice. Too bad the Open Props forms isn't ready yet. I can send you the CodePen for it.
Jason: If that's not ready we can do something else.
Adam: The normalize does do minor things so they are light and dark themed. It is worth checking out to see what you get with inputs with just the normalize.
Jason: Let's do it. We will setup a new function that will be the form and that's going to not mean anything so that will return -- we will setup a form. For now we won't have it submit anywhere and we can setup -- how do we want to do this? Let's do a label. I am just going to use a label to wrap around -- should I wrap around the input or set it up with separate entities? What's going to work best?
Adam: If you wrap them you don't have to do the ID and the pointing.
Jason: That's what I was thinking but I wasn't sure if it would mess with the Open Props. Let's do that. I like doing that. To give us the ability to go block with our label but not any semantic meaning we will do something like this. In here we will do input type, text, and that's good enough. Do one more of these. This is going to be an input type date and more of these. This one will be the guest name. And I think I might skip the image input unless you really want to do a file input.
Adam: You can see what it looks like. It is styled minimally. Input type file? Yeah. You can pass in like a matches thing later and try to have it only pull in images or something but yeah.
Jason: Here is our -- weird. Already out of the gate looking nice. I am going to go in here and give this a class name of styles form. CSS --
Adam: CSS modules is so cool like that. Just going to name it something easy and short. Display grid with gap some start?
Jason: Yup, yup, yup. Display grid. The gap we will set it up to be var size 2 looks and I am also going to set a margin -- is it margin block or start?
Adam: Block is the top and bottom and block-start for the top.
Jason: It was size, fluid --
Adam: Yup. Look at you go. Oh, man, we haven't got into the gradient or the masks or the easings or the animations but you know, it is all good.
Jason: So many great things but look how far we just got with this little bit. Now I can do form label span actually because why not and we will do a display block. All good. And then we will do a form input because they are all inputs and we can do a width -- is there a -- if I am going to do this, is there a smart thing in Open Props?
Adam: Nope, a 100% is good to go.
Jason: Look at that, y'all. This would be the way we would setup a new episode. We can just build it right in here. Then we go to do one of these and it would open up file selector. This is all just very nice. I love this just looks like it is part of the system without being overly styled or anything like that. There is there animation.
Adam: There is the animation. I saw it. I don't know what was up before but there it is.
Jason: Really, really nice looking. OK. We got a form. Honestly, that's no joke, that's the fastest I have ever made a form in my entire life. This form looks nice and I have literally spent -- we spent 3 minutes on that maybe?
Adam: No check out the CodePen link I sent in the ping chat. I sent you a couple links.
Jason: The first or second?
Adam: Click them both. The private looking one is the one for the form inputs. This is all the button types. When you import buttons and change the type this is what they look like. Look at button custom there. To override, no battles, make a class and put styles in it and you are good to go.
Jason: Beauty. Let me pull up this other one.
Adam: This is the future of the forms once I work out the kinks across browsers and stuff. Look at those dark themes. They have icons in there. If you look at the code too they are vanilla inputs. Just look at that. It is just a type text.
Jason: Oh!
Adam: The buttons, how the style follows the type of the component itself, same thing with the inputs.
Jason: That is beautiful. This is wonderful, right? This is so nice to see. I think what was it? We talked to Dan about this. Styling with attribute selectors. This was a very cool setup and something I would highly recommend everybody checks out but this is very cool. Do you mind if I share these in the chat?
Adam: Share. The only reason -- definitely share those. I would love to get more feedback and tell me what you look for in an easy form import. Does this do too much or too little for you?
Jason: We have this nice-looking dashboard. The next thing I would like to do is maybe I want to add a notice up at the top about something that's happening and I want to give it a big, beautiful gradient to check eyeballs and maybe it animate as little bit so people make sure to look at it.
Adam: That's sounds good. One thing before we go. The date inside the card, will you give that var text 2. That will bump its contrast back. Text 1 is being very contrasty and the text I want to be red and subtle text or small text or ancillary text is great to give that var text 2 so you are still within accessibility but it pushes it back subtly. We wanted the date element in the card. Do card and then space date.
Jason: Date element within the card? This one? OK. I was working in the form. Let me go give this one just the date element. We will do a card date.
Adam: It should be subtle but that looked almost so subtle that we didn't see. Try a color or just do indigo5.
Jason: Everybody watch. It is working. I am going to save 1 and this is going to get brighter.
Adam: It is subtle. We are just subduing it to make way for the primary thing you want to read which is the person's name and the title there.
Jason: That's very nice. That's what we want, right? OK. So then let's go in here and let's make a --
Adam: Animated banner. Good call.
Jason: This one is going to be let's call it an aside. It is going to have a --
Adam: I just thought of a bad HTML joke. Have you ever have an acai bowl? Aside bowl? Flop. It was a floppy floppy prop.
Jason: We have caused physical pain to the chat.
Adam: Everyone is like and we unsubscribed.
Jason: The metal orange is here in appreciation for that joke. Welcome first time, chatter. OK. Let's put a note in here. Please remember to include a photo with every episode or my crappy software will fall over. That's a good note that is important to include because it's true. I am going to put this in here.
Adam: Perfect. That needs some prompts, man.
Jason: It needs some things. We could just style directly on the aside but in the interest of CSS prompts I will give it a class name and call it styles-banner and we will drop this in here. We are up above the card, up above the table even. Anybody picking up on all my nice obsessions around how to organize CSS? I need like -- what do I need? I need a little bit of margin start. We will go with a var side 4.
Adam: Do margin inline block start. Perfect. Let's give it a little padding as well. That will make sure our gradient has some space around the text.
Jason: We did what? Like a size 2 and a size 4?
Adam: Yeah. Very nice. Well, let's just throw our gradient on there. Background: var gradient 1-30 or whatever you can pick up. If you click docs at the bottom you can get a preview of what those all are.
Jason: Look how fun this is. They are just scrolling on through. 2 is currently my frontrunner. I like 2. What's this one? Black-on-black. That's the Batman gradient.
Adam: So many of these gradients are harmonious for reasons you can't explain but I can. A lot of them are radial, a lot are conic but they look linear.
Jason: I just want to take a moment to appreciate. OK. Dumb-dumb. That's so good. [Laughter] OK. I think 2 looked great. There are a ton in here. Radial gradients are awesome. I do really like the look and feel. I love these multi-mesh gradients. They are so freaking cool. But this -- now looking at this I want a little bit of text shadow. That feels like it will make that text pop right off here.
Adam: I don't have text shadow prompts but it is in the backlog. If enough people say I would like to see var text shadow 1-4 I can make it.
Jason: Maybe I can just do a color and set it to the background.
Adam: Do a var surface 1 so it will pull in the color from the background and that will look cool.
Jason: There we go. Real subtle and pops it off the gradient to keep the legibility high.
Adam: I think that will adapt and not look good so let's try gradient 5. The gradient won't change but the text shadow will. It will adapt. The text and surface colors adapt. Yeah, something dark. The higher numbers are darker. Cool.
Jason: There we go. I am happy with that.
Adam: Rad. What do we want to do next? Should we animate it?
Jason: We want probably a little border radius. Let's see if I can do it from memory. Radius 2 is what I think we have been using. Now it matches and I want a box shadow to also match. So my box shadow, I forget which one we used, let me look at my card.
Adam: Shadow 4. This comes into a cool conversation where there is global prompts which you imported and you will start eventually creating local prompts. Like you said my design is going to use more shadow 4s than anything else. So you can make your own prop called my branch shadow and it can be backed by Open Props so that's nice. You start a prop stack with your own custom inhouse ones supported by these global Open Props one.
Jason: I just did a thing to attempt to create hierarchy which is adding height to the banner with a bigger shadow and dropped the height of the cards with the lower shadow and who knows if this is like advice from Jason, take it with a grain of salt, but these look nice and tight. This look like it is floating over the top. Let's animate that to make it feel, you know, grabby.
Adam: Click the animation link in the doc site and we can preview all of the prompts you get to play with.
Jason: Animations. We have fade, shake, oh, you got these built in. That's awesome. I thought I was going to have to do more. Ping, bounce, pulse.
Adam: Scroll down more and you can see them. They are all interactive. Try them out. Here is fade in, fade out. Nice.
Jason: Nice. Nice. The slides all make sense to me. Let's do a spin.
Adam: And those are infinite and so is pulse. Well indeterminant or whatever.
Jason: Bounce. That would be like if you have a notification somebody needs to deal with. Float is fun. Oh, this feels like the thing. What's a ping? That's too much. That's too much. [Laughter] The blink looks pretty good. Oh, maybe the shake is the right call. Hey, look at me. I am going to do that.
Adam: Perfect. You will do animation.
Jason: Animation shake wide?
Adam: Instead of animate it will be animation and I think that's it. Animation shake wide. You are done.
Jason: Any time you reload this page it is going to be like yo, read this, which I love. That's exactly what we were going for. It is not super overbearing but it is eye-catching.
Adam: Let's also animate the cards in. Want to slide them up? Slide from the left? We can do cool stuff there really quick.
Jason: Yeah, I think I do.
Adam: If we slide them in, we will add the bounce easing so you can get nice bounces for free too.
Jason: Yup, yup. If I do animation -- it was slide in.
Adam: Slide in right? I think you have to pick a direction. If you want, you can combine that and do comma animation fade-in. This is where Open Props starts to blow minds. People didn't know key frames could be composable so the merge and the fade-in with the slide at the same time and time it for you. We have to set opacity 0 to start from a fade out state. There are ways around that which get more advanced but not that much. So we have opacity 0. We need to do var animation fade in space forwards that way it fades in and sticks the play head at the end and remains faded in.
Jason: Ah, I get it. Then we want to do an animation delay so what I can do for that --
Adam: You got the map already in here.
Jason: Yeah, I got the map already in here which is down here.
Adam: The map, the map, the map! Sorry. I am a dad.
Jason: And I need to pass this in --
Adam: You can write the delay or make a custom property and do in the CSS.
Jason: I think I need to pass it in as a thing because we aren't inheriting the others. Index equals I. Where is my card? Let's collapse the banner. Here is my card and let me get my index. With this one we will do a data count equals index. Then what we can do in here is a card -- no.
Adam: There is a slightly easier way. Do animation delay and then here set it to your variable. Data attribute, yes. I don't know if it will pull that in. Let's see.
Jason: You better work.
Adam: If it doesn't we will put the prop inline as a custom property. That seems OK. We have the data count.
Jason: That doesn't work. I got to do it different.
Adam: Do style equals instead of data count style equals and then we will make a property on the fly --_delay or something like that. You don't have to do the underscore. The value of it is your index. And now you will have that custom property.
Jason: So I can do index. We could do this a bunch of ways but I am going to do as var --
Adam: Yup. There they go. Staggered in.
Jason: Let me make it way slower so everybody can see what just happened.
Adam: Underneath our animation delay we will modify the way it bounces in. Var--easing Elastic 3 will do that. Oh, I didn't quite see it. Was it there?
Adam: Let check the easings. Ease Elastic 3.
Jason: Ah. Boing.
Adam: If it is too strong drop the number down and do ease Elastic 1. Little more subtle Elastic effect.
Jason: And maybe we can -- what's squish?
Adam: If you scroll down in the doc you can try them all.
Jason: I love squish.
Adam: Squish is nice because it does a bounce at the beginning and end. Velocity will do it but squish does it on both sides at the start and end.
Jason: This is really nice looking.
Adam: There is the five easings compared against each other. What Open Props does that's nice is you only have ease, ease in or ease out and a couple basic options built into the browser but this makes five flavors and adds Elastic, squish and steps and you can preview what they look like here.
Jason: That's great. Oh, God. This is awesome.
Adam: We animated it, customized it, got Elastic in there and a gradient.
Jason: This is awesome. I am very happy. We were able to coo doo a lot of things in very little time because the piece that usually trips me up with CSS is that I will start to see a style emerging as I start messing with things and then you kind of have to go back and tweak and tweak and tweak and as you all saw when I added the banner I wanted to mess with these shadows to make this feel more important instead of having all these at the same height and all I had to do was knock the number down a bit. I feel like that is such a cool like iterative sort of thing. As a prototyping tool, this is going to change a lot for me personally because I can just like whip out a quick here is how I think this should feel and later I can go in and override and do custom prompts and make general customizations but man, it is nice to throw something together, right? And this is the sort of thing that like if I were to build this on my own, and everybody has seen me do this, you have seen me build aps from scratch on Learn With Jason all the time and they end up being unstyled and I have to go make that look nice later and generally I don't have time to do that because I have 90 minutes a week to write code. That the unfortunate circumstances of my job right now. Vinny is like yeah; we have seen you struggle.
Adam: I struggle too. This stuff is hard.
Jason: Just getting wrecked by the chat. This is really wonderful. So, chat, questions? Nicky is kicking it off with a question before I got to say it. Does this do the tree shaking thing where only the variables you use are included? It doesn't because we are still going from there general import. Why don't we fix that. Let's go clean this up. I am using nex.js and I am going to put this back over here so we have a little more real estate to work with. If I want to take this out of the unpackage import and into a more production, let's use post-CSS or not necessarily post-CSS but how do we get this into nex.js in a more build systemy way?
Adam: We talked about git drops which doesn't work for CSS modules. There is a clash of ideals between the scope of that class. You can use prompts but you have to put them into the global space. For this you can use un-CSS that will remove unused custom properties for you. There is a way to take them out versus yeah, git prompts only put in what you use. There is an additive strategy being minimal and a subtractive strategy but there is a third one which you can do. If you npm install Open Props. Npm-i-Open Props. This will kind of make it --
Jason: We are using yarn. It looks like they kicked us off so we will stay there.
Adam: Look at that huge download. For imports, get rid of the https part and the min.css part. So now you are accessing these styles through the modular exports, the package exports, so the short import pass I mapped them to actual CSS files. Look at that. How does it not know what Open Props is? We just installed it right?
Jason: It doesn't like Open Props?
Adam: Try openprompts/styler. Depending on the bundler -- I have done work if you import Open Props from JavaScript which by the way these are all in JavaScript. If you want to do style components or emotion or something and want to use these prompts in your JavaScript you can import all the tokens that way. That's what that mix up was. They were like I found JavaScript at Open Props and my thing didn't map it right. Whatever. Styles specifically if you want to style file. If we want to be minimum from here, well, what we need to do is not import style. Style is all of the prompts. There is like 350 of them. This gets kind of hard. We used normalize and it uses a bunch of prompts and we don't know which ones it used. So the idea of being minimal I was going to go with -- nice tweak. Got to use that new component.
Jason: Can I have an aspect ratio? Dang it. What's the -- I don't like this.
Adam: If you set width it will set aspect for you I think. And we have an aspect ratio I think in our CSS. Must use width and height.
Jason: If I make it layout fill -- I have issues with next for this next image thing because they fail your builds if you don't use next image and they require you to do a bunch of config to get it work and it is like don't be like that and don't make me do that. I need to add sanity.io so it doesn't explode. They don't show me the actual code. OK. OK. Module.exports next config I need is -- now it will maybe not yell at me. It broke my freaking prompts. Kick it like the Beasty Boys. Don't make me pull styles into my stuff because now I have to like tweak this and it breaks all my other stuff. This is now no longer in my CSS. It just isn't my favorite API. I feel like it has opinions that are not -- they don't jive with me. Anyways we are not talking about Next. I just wanted that warning to go away.
Adam: A third strategy is importing what you use. So import gradient, slash easing/animation and you can manually reduce the bundle by importing what you know you used. It gets a little difficult with normalize because it mostly uses sizes so I don't think you will run into that many issues.
Jason: I feel like we are going to lose cep some stuff.
Adam: We need the gray colors. I think it is just gray.
Jason: We are missing our border radius.
Adam: Borders, our shadows. We need the typography. Oh, maybe it is -- what is my import name here? Package JSON exports to see what the name of that one is. Types fonts. Did we get everything?
Jason: I think so? What else are we going to see here? We have ratios. Animation. Gradient radius. Shadow size gray. Animation. My custom thing. Easing. Surface. Do we need do anything for surface?
Adam: No, those are defined in normalized and it backs the surface with gray. Our link color failed because we probably need to import indigo. If you have the git prop way when you import it normalizes them all for you. All in all, the prompts bundle if you get all the prompts it is really tiny. And yeah, you never know when you need them.
Jason: Yeah, and we can check like bundle phobia. This is not going to do what we want because it is not going to do the individual exports. It will do the whole package which isn't really helpful. I feel like when you do that with something that's properly tree shaken it gives false information. This though is looking really nice. You know, we saw how quick that downloaded. It clearly isn't a big library even if you import everything. If we look at the network tab here, let's see, let's go for just our CSS. We are in dev mode so everything is in JavaScript.
Adam: I have the file sizes on the doc site if you want to check them out there.
Jason: Lovely.
Adam: Under the demos and sales pitch and right here in the overview.
Jason: Open Props.mim is 3.4 kilobytes. If you are importing React into your site this is not the piece you need to worry about.
Adam: That's the idea. You can go git prompts if you are really trying to shave things off but most of the time I don't think the prompts will be making the bundles explode. Can we do one more random thing before we wrap a little? We just deployed some new masks in Open Props and they are really cool and really easy to use. Pop to the top and add a prop.
Jason: Pop to the top and add a drop we are dropping swappy prompts.
Adam: And just do mask? Or I can it is mask.edges. Did it fail? Yeah, it did. Masks -- oh, I did. Masks/edges. And there is also corner ones too but we will try edges first. Now we will go to our card and add a style to it because we are going to give basically the right side of it, we will give it a little edge. In here you will do webkit-mask and then you will say var and then open up the doc site and we are going to go shop. We are going to shop some masks. This is a fun part about Open Props; the shopping. At the end you will find it in the links. They are brand new.
Jason: Rad edges. I love it. We got scoops. We got scaleups. Drifts. Zigzag. Let's give it a zigzag. I am going to go in here. I have my mask edge zigzag right.
Adam: They are just stupid and fun, right?
Jason: Yeah, that's the most anybody can hope for.
Adam: How dare I make this fun. This shouldn't be fun.
Jace: And I am going to give it a bit more pad here so give it a 6.
Adam: Those are new. We will be adding more masks. There is ideas about icons so I can send you a thing where it is easy to mask an icon and use an Open Props gradient on it and they look great. These are sub-atomic and they are just named values for you to use as your own free will to go be creative and fun with. The normalize is nice if you are trying to start new and want a dark and light theme or you can build your own and import any reset or normalize you like to use and start building with the prompts. Super out of your way and hopefully feels like wind beneath your wings type of things.
Jason: Open Props you are the wind beneath my wings. [Laughter] I love it. This is wonderful. Let's see any questions here? I don't see any additional questions but I do see a call from Cynthia to drop the Open Props discord which is a pretty good transition into where should people go if they want to learn more.
Adam: Yes, the Discord is great. There is a lot of discussions of things coming out in the future and more prompts we want to name. You found it off the website. Perfect. I don't have to share it. With you are in the Discord you will see us talking about new prompts and people asking questions about various issues they have. It is usually SaaS or import related. The number one most asked question is my import isn't working and usually they need to add slash styler. For veet you don't have to add that. It knows to look for the CSS file because it is a CSS import. Others are more naive and need a little handheld but yeah.
Jason: Love it. I dropped the openprompts.style. This is a comprehensive set of docs. I love the way it is setup. We have general setups. And we can get on GitHub, Discord or Twitter. Let me pop the Twitter open.
Adam: It went to me. It should go to Open Props but that's OK.
Jason: We also have Open Props. No dash, that's right. Open Props. So you can go give that a follow which I am about to do. And now we have got Open Props News right there in our stream. Just every day we can see what's new. Adam, very nice. Any last words before I do the tear down here?
Adam: There was a cool link at the top of the doc site for open or try in browser. If you want to just try git prompts with Veet setup give that a look. It is all ready to go. I am so happy we are cool again because I have been using it. I am like great. I don't sound old.
Jason: This is rad. If anything is rad this is rad. I love the ease of use. It didn't feel like I was learning a new language. Everything is natural and pleasant. The docs are navigable which is great. I don't feel like I am bouncing all over. It is just one page. This feels like something I will feature in my prototype and potentially in the way I build things in production, well if I ever build anything in reintroduction again. But my rapid prototype got a level up because things are going to be beautiful without much time which I am sure the chat appreciates that I am not spinning in circles in CSS for 45 minutes in an hour long building.
Adam: We talked about the swappy prompts. Let's put it on the cards.
Jason: What do I do?
Adam: Radius conditional 2 I think. The same amount of radius you expected but when they go full width it should go away.
Jason: Full width and I will get rid of that. You can see the difference because this one isn't not a swappy prop and this is. It did what we want it to do which is exactly what I want to happen when I'm building fluid layouts. Swappy prompts for the win. This episode like every episode has been live captioned. We have had Maggie from White Coat Captioning here all day. That's made possible through the support of our sponsors Netlify, NX, and New Relic all making the show more accessible to more people which I appreciate. Check out the schedule, subscribe on Twitch and YouTube. Make sure you don't miss episodes. You can find Google Calendar. You can find me on Twitter and Adam on Twitter and all sorts of people. I think we will call this one a win. Adam, thank you for being here. Chat stay tuned. We are going to go find somebody to raid.