字幕列表 影片播放 列印英文字幕 CSS Algorithms Lara Schenck KATIE: Hello. Hi. Oh, all right. How is everybody doing? Yeah? Whoo! I know we're all hungry. But this is our last talk before lunch. And I think it's gonna be an amazing one. We have Lara Schenck here to talk to us about CSS algorithms. And so, Lara's fun fact that she gave me is that she grew up on a llama farm in rural Pennsylvania, very small town. And I asked her, well, can you tell me some cool things about llamas that people wouldn't necessarily know about in their everyday life that's llama free. At 4H competitions, there's a bunch of llama categories that you can enter. So, llamas can do agility runs. Kind of like, you know, you've seen the dogs that jump over hurdles and they go in between poles. That was not her specialty, though. Her specialty was the llama costume category. Where you dress up yourself and you dress up your llama. And she won a blue ribbon for her rendition of she was the tinman and the llama was the cowardly lion. And she said there's probably a picture of this somewhere so I'm going to really encourage her to have her parents take a picture and send it to us so we can go and find it later and see a picture of her prize winning llama costume. All right. So, let's give it up for Lara Schenck. Take care. [ Applause ] LARA: Hey, everybody. Wouldn't it be great if I want in a tinman costume? Yeah, I don't know how I'm gonna follow that story with my talk. I wasn't really prepared. Yeah. Welcome to my talk. CSS algorithms. I'm really excited to be giving this to a room full of people at a JavaScript conference. And the best thing is I have met so many great people that, oh, I'm giving a talk to my new friends. Isn't that nice? Nasty, friends, before we get started talking about CSS algorithms, we have to answer a very important question. Is CSS a programming language? Fire emoji. [ Laughter ] How many of you have seen this question where there's related drama about this topic on Twitter over the last year or so? Yeah? Okay. Depends how many people use Twitter, I guess. I do have a question. Like, does this drama come up in real life also, or is it mostly contained to Twitter? Anyways, we have to answer this question before we talk about algorithms. So, I asked this question on Twitter. First in March of 2018 before I gave version 1 of this talk. This is on 3.5.1 now I believe. Is CSS a programming language? What did Twitter think in 2018? Any guesses? No. So but it's pretty split. 42% yes, 50% no, 8% I'm not sure. Not a huge dataset, 129 votes. But the answers to kind of the responses in the comments are very varied. So, it was either like, yes, absolutely. Or, of course it's a programming language. Or, I don't really consider CSS programming. Or you can't call styling a web page programming. It's not really a programming language. And things like that. So, after I gave this talk a little bit, before I started giving it again this year, May of 2019 I asked this question again. And I was like, nobody is going to answer. Okay, Lara, we see what you're doing. We saw your talk. Okay. No. This time [ Laughter ] This time the poll had 5324 votes, which is definitely the most activity I've had on a Tweet before. And the noes increased. I was like, what's happening? What's going on? And not only were the same kind of varied responses in the comments, but there were also people that kind of specialize in HTML and CSS that were saying that I never call myself a programmer. And things like, why are we concerned about what CSS is? We should be concerned about what it's doing, et cetera. And things like stop asking this question. Don't wake the beast. So, stop. Like, everybody, stop. We have to answer a different question before we talk about is CSS a programming language. What is a programming language? Before we decide whether or not CSS is one of these things so, not surprisingly, there are many fields of research and people have dedicated their entire careers to answering this question. And we can't be really specific about what a programming language is because there are so many types of programming languages. So, the definition kind of boils down to there are lots of different ones. But could boil down to a formal language for instructing computer to perform tasks. This is Wikipedia and several others. Some good articles out there. The important part here is language. It's a language. And there are different types of programming languages. And these kind of fall under the categories of programming paradigms. And we use programming paradigms to both describe languages themselves as well as the style of code that we write. So, the two main paradigms are imperative which is code that describes code that tells a computer how to accomplish a task. And declarative. Where you tell a computer what to do. So, the language the expressions in the language are saying what, not how. And the main difference is the presence and absence of control flow. And so, control flow is the ability to manipulate the order of executions of statements in a program. So, control structures like if statements, for loops, imperative languages have these, declarative do not. Any logic is baked into the statement itself. What are some examples of these programming languages? Hmm m... imperative languages. JavaScript, of course. Ruby, C + +, Python. These are what we usually think of when we think of programming languages. Often times general purpose languages. Declarative languages are often, not always, domain specific. They are built to function within a certain context. What are some domain specific declarative programming languages? SQL. It is a declarative for data bastes. HTML, adding meaning around content on a web page, CSS for styling the content on that web page. Loud and clear. CSS is a domain specific declarative programming language. 100%. CSS developers program the layout of web pages. boxes. Let's be honest. Everything is a box. CSS programmers are box programmers. Also 100%. Okay. So, cool. Like, great. Like, maybe I can win a Twitter argument at some point. Good job. Why do we care about this? Why do we care if CSS is a programming language or not? So, I want to talk about something called Turd driven development. Of course this is a rift on test driven development, one simple in both is all code is crap the first time you write if. It is not possible for a human being to write perfect code the first time you write it. So, in test driven development, you kind of counter this by starting, instead of writing in production code, write a failing test first. In CSS, we don't really have this kind of testing. You can kind of say the test is the design. It's like, okay. This is why am I failing tests? Yes, I see it. It doesn't exist yet. So, yes, the test is failing. Run the test with our eyes. What do we do? We write code to make the test pass. So, all code is crap at first. We write some crap CSS. And then what happens? We stop. Okay? The CSS, it's done. I don't have to write anymore. Oh, wait, the test is failing. There was a change to the UI. Some new feature. The test is failing now. What do we do? We write more CSS. The test is passing. Oh, wait, maybe there was a regression. So, now our test is failing again. So, we write more CSS. Okay, whew, don't touch it, erg is working. And then we wait. And, oh, wait, new feature. More CSS. Test is passing, oh, no, another regression. More CSS. And so on. Wait here we go. Oh, wow, what's happening. Our tests no longer completely passes. And this is what happens. But the problem is this is the web. This is the frontend of our web applications. This is what People use. And this doesn't just apply to CSS as a language. But also HTML and also JavaScript. It's kind of this culture of how we program. So, what do we do? Ah! Oooo! This is so bad! It's so bad! All this crap everywhere. What do we do? Stop writing CSS. Start programming. Okay. So, the thing is, programming does not equal logic, math, science, engineering. These things can be part of programming. But programming in its essence as an art, as a craft, is writing instructions for computers that other developers are able to read and maintain. And I think if anything shows that CSS is a programming language, it's that naming is really hard and extremely important. Naming is one of the hardest problems in computer science CSS is part of that story. Unless you're writing CSS in JavaScript. Okay. Okay. So, cool, we got if. We've covered a lot of ground so far. Now let's talk about algorithms. Now that CSS is a programming language, how do we write algorithms in this programming language? Hm. Algorithms 1013 let's have another definition. An algorithm, a well Defined computational procedure that takes input and produces output. This is from Thomas Cormen who wrote the book, the introduction to algorithms that is assigned in many the computer science course. I read the introduction. [ Laughter ] Might revisit. Okay. So, a well defined computational procedure. Input and output. Let's use this little board to help us visualize. Common use for an algorithm, sorting. We have a list of unsorted numbers. Our algorithm, the output, our algorithm should transform that input into sorted output. Hm. What are some sorting algorithms? I know this crowd probably knows some sorting algorithms. Bubble sort. Selection sort. MergeSort, quickSort. And could go on, but we'll keep it at that. Okay. What does an implementation of a sorting algorithm look like? Name that sorting algorithm. Bubblesort. This is imperative JavaScript. Cool. That's fine. If this was declarative code, it would be secured behind the source. We're telling not, not telling the computer how to do it. What about another kind of algorithm? So, how could this possibly apply to boxes? Okay. So, our input is a stack of unsorted, unstyled boxes. And our output, we want this to be a row of boxes. What kind of algorithm happens in between? Well, display: Flex, absolutely. float: Left. Gasp! [ Laughter ] How dare we? Yes. Floats still have their place in this day and age. Okay. What is an implementation of these algorithms look like? Well, this is what we see. This is declarative CSS. There's a big huge algorithm under the surface, but display: Flex is all we have to write. If we expand on this, this is what declarative logic looks like, what, not how. And under the surface, this is what's happening. This is a little snippet of Rust code from the experimental rendering engine called servo being pulled into gecko in Firefox. And this is where the wrap is happening. There's an imperative backbone to any code in CSS. Let's have a iceberg metaphor. Love a good iceberg metaphor. We have CSS on the top and imperative code on the bottom. Oh, my god, so many browsers in here. They are complicated. can we call the CSS algorithms? Hm? Algorithm? Why not? So, let's go on the premise of all the work I have been doing. What happens when we call that an algorithm? How far can we take this? Let's update algorithms 101 to CSS algorithms 101. Domain specific, declarative. These are magic words for CSS. And in term little of a word like algorithm or any kind of analogy to general programming, it's by definition going to be different in CSS, domain specific, declarative, you have to understand the domain to use these. A definition, a CSS algorithm is a well defined declaration or set of declarations that produces a specific styling output. Me. So, key points here. Well defined and specific. An algorithm is not a block of however long a set of declarations can get. But you're solving a specific problem. And I also think an algorithm is when CSS goes from being this mundane styling language like font size, color, whatever, to something where you're like, whoa! CSS! Like, what's happening? This is so cool. And you kind of appreciate the fact that you don't need to write so much code because the language is doing it. We can understand the language and understand how to communicate with the browser. So, you know what this notion is. This well defined set of declarations. So, as I was thinking, I was like, okay. I'm going to pick out some common algorithms that people would recognize. And the first one I thought of was this. Clearfix. So, oh, god, sad face. Like, that's a hack. Clearfix is not a fun algorithm. Could be an algorithm. Okay. What about this? [ Laughter ] So, this is a very long class name and not actually the name of the class. But you get the idea. And this is very amazing and elegant that you can do this. Let's say you have an element way out here. Positioned relatively. You can no matter how far it's nested in nested into that, that child you can kind of pop out of that whole DOM structure and stick it to the top right, bottom right, whatever. That's cool. Positioning. It's cool. Spaced content. Has anybody used this before? It's kind of a selector pattern. Lobotomized owl. Someone named Heydon Pickering came up with this. This is a way of spacing content with another content without adding to the top and bottom. This one I like. It's kind of a fluid typography. So, we use a viewport unit to make the size of the text element more fluid. And this is a linear interpolation. Math. Cool. So, yes, that's grid. Oh, my god. These two lines of code, we can make so many grids. Add a couple of spans in there and this is the most robust grid framework you'll ever need. It's not a framework. It's just code. Oh, my god, so great. So, CSS algorithm, a well defined declaration or set of declarations. Specific styling pattern. I haven't updated it. A CSS algorithm is a utility pattern that lets the browser algorithms do the work. And I think a CSS algorithm also follows some programming best practices. So, a single responsibility principle. Let's say we have a set of kitchen tools. So, the wooden spoon is so good at being a spoon. The whisk is great at being a whisk. Spatula is great at being a spatula, knife, knife, et cetera. What happens when a tool tries to do too much? [ Laughter ] Sad. This is a spork. A spork. I'm sorry, spork, but you're just trying to do too much. It's not that useful. People aren't that excited about sporks. Although there is a restaurant in Pittsburgh named Spork. Why did you do that? Anyways. Small, well named functions. This was a good programming practice. How small should your function be? Small. And then smaller than that. So, these are the words of Robert C. Martin in a book called Clean Code. He's kind of one of the inventors of a lot of agile software development practices. Okay. This is all well and good. What about in the real world? You're probably not writing the next Clearfix. So, I work as a design engineer at a company called Penske Media Corporation, PMC. We're a big publisher with 24, I think, different very large brands all on WordPress sites which is exciting. This enterprise WordPress environment. Sometimes I call myself a design Ops engineer. I love my job. So, give it some hearts. These words also equate to UI engineer. Also, the design systems at PMC. Also, the first and only frontend developer in team of many backend developers. However, not anymore. We hired another frontend developer recently and I see that as a major sign of success. Yes, a company that went so long without frontend developers now has two. This is cool. This is like, yes. PMC cares about frontend. So, my work has revolved around the development of a design system called Larva. Yes, it is called our design system is called Larva. And it is an embryonic design system. It's a good name for it. It's a little baby. It's not this beautiful UI library of components. But it's tools and best practices to build modules and comments. Embryonic. This is a laboratory to try out all these ideas, what is an algorithm? How does this work? So, Larva was built inside of a project from a site called deadline. And this is a WordPress theme. Kind of the base file structure here. And then drilling into a source directory. This is an IT CSS architecture. Triangle CSS. I added at the beginning of the project a directory for algorithms. I was like, will this be useful? Would this will we actually add anything to this? And yes, there were like 20 something algorithms in here afterwards. So, kind of proved to be this useful naming convention and useful way to think about styles. And since this project completed, the process has been like moving all of this code into a shared repo. So, project structure that might be familiar to some is the monorepo structures. This is like Laravel 1.0 and these are npm packages. We have kind of the CSS npm package. Inside one of these algorithms, a glue, which is a pretty weird name for a style. There's a SaaS file, or a CSS file. And an HTML file to give an example of what the markup is. And a glue is this algorithm. But we've kind of turned it like design systemed it to be more reusable and a little more robust. So, it has different namespacing and we use the term glue because it's a nice mental model for what it does. Glue a UI element within another UI element. And this was used like 15 times in the deadline project. Not only by me. Mostly not by me, in fact. So, there was another contractor who was like a little more junior and they understand what this did. Whoa, this is a cool way to communicate the CSS concepts that might be a little hard to understand at first. Another algorithm, space children. Whoo space children. So, this is the lobotomized owl. And design systemed, this looks like this. So, I could have some progressive enhancement inside this algorithm. It's kind of pulling this functionality into its own little node. Into its own little section. We can do really interesting things. So, column gap is a new property in some browsers and we can add this feature query inside the algorithm. In markup, this is what it look like. So, pretty heavy use of utility classes. And the algorithms are kind of layered in among the other class names. Like an onion. But algorithms can also be useful for stuff like this. So, if you've ever got an design and you're like, god damn it. This is a really pretty border. But this is a very annoying thing. Why do I have to develop this? So, you can be like, I'm gonna pull this out and I'm just gonna write this border. This border code. And if it shows up in one design, it's probably going to show up in another one. So, an algorithm can be a nice way of handling that. Okay. How to write a CSS algorithm or realize you don't need to. How to write algorithms? How you write an algorithm in an algorithm interview? Has anybody done a whiteboarding interview or an algorithms interview? A few? Yeah. No more comments. [ Laughter ] Okay. So, the steps. These are kind of taken straight out of cracking the coding interview. Plan your algorithm. Then you run a brute force solution. A not optimized version that steps through piece by piece. Slow, but maybe it works. And then you do a walkthrough in the interview to make sure the algorithm is functioning and then optimize it. Layer different optimization techniques. What about writing CSS algorithms? Well, you start by planning. Planning out the algorithm. Then you write brute force solution that's not quite optimized and walkthrough. Same thing. Except there's some pre work when you're writing a CSS algorithm which is doing a turd check. So, you'd stop before you write any CSS and say to yourself, should I actually be writing new CSS? Like, what is going on? Have I solved this problem before somewhere in this codebase and why can I not use that again? So, just a quick moment to be like, wait, is this really the problem I should be solve something and then you plan. Pseudo code and boxes. Pseudo coding CSS and defining your problem. What is this thing you're having a hard time with that you need to solve? On paper, I love drawing boxes on paper. I love to do other things too. But sometimes this is really fun. Also because writing things on paper and like whiteboarding, there's research that shows we have better human beings have better retention when you're doing things in physical space like that versus drawing boxes in Illustrator, et cetera. Also, printing out the design and marking it up in that way could be really useful. Figure out what if you're working with an existing system, what patterns are already provided. What do you need to write new? And a brute force solution. Spaghetti, write gross code, that's fine. And remember the assumption, all code is crap at first. Don't write it in the actual stylesheet. Write it somewhere else. Instead of inside the main application, you could have a separate file. This recent project I was having a file called scratch pat.scss that was added to a test environment, not to an actual application. It was a safe space to try out the CSS. This is what it ends up looking like. Working with boxes. CodePen is like a product for this specific use case. For writing frontend code outside of a regular environment. And this is a the little border arc. Our story border arc from before. So, do a walkthrough. We love resizing our browsers. Web developers are like, yes. Not going to test it in a different browser, but I'm gonna resize it a lot in this one. So, that's a walkthrough. But test it in other browsers. And it's a lot easier to do that when it's a small piece. So, it's easier to do it now. Ask yourself, is every declaration essential? Are there any dependencies? Does this algorithm need to be applied with another class and why? And this you can have a Robert C. Martin in the back of your head that's like smaller, smaller codes. And then you can optimize and refactor and document. This is when the magic happens. When our poopy code becomes a flower. Of course. This is how programming works, right? And this is when you're moving that crap code, the fact that you need to move it into the actual codebase, that refactoring will happen naturally. So, moving from this set of boxes to an actual layout will improve your code. Document. So, inside our deadline program library we had documents, a paragraph about what it's doing, how to use it. And then boxes. Show what it's doing. So, I feel like this with this process turd driven development can kind of become more like test driven development. With CSS? What? So, what if we had thought about it like, oh, our test, instead of being the entire design, is a smaller piece of the design or a specific piece. We run the test with our eyes still and write our crap code. But the refactoring, putting it in the code, can give us that additional step of refactoring. Again, a beautiful flower. Refactor the missing piece. Let's be real. But less looking poop is greater than regular poop. But what if, so, this is a little experiment that's coming up here. What if so, test driven development. I have been writing tests for other parts of our design system in JavaScript and I'm like, I love writing tests. There's some magic, like straight up magic when you write good tests. And I want to do this with CSS. How can we write unit tests for CSS? Domain specific declarative tests? I had an idea and wrote enthusiastic blog posts about it. Testing algorithms. So, warning, this is a big code slide and kind of a prototype of something I'm trying out with a little bit of client side JavaScript. For one of the CSS unit tests, what it could look like. So, this is essentially a couple of test methods that log to the console. And the crux is you're testing boxes against boxes. So, you're figure out relative values of certain positions and boxes and comparing them. And what this looks like in practice. The unit test might be with the minimum amount of HTML. And we're logging into the console. But this could also be an integration test on an actual application. I ordered this to the deadline staging environment and actually found a problem with this. So, this showed me that there should not be space below the last item. But there was a different set of styles that was adding that space, which is incorrect. That will cause problems later because if someone adds another widget to the side bar, it's gonna be too spaced out. And that's what cause this is like turd driven development. Especially with CSS, oh, you override it instead of going back to change the actual issue. Ah! This could be cool. So, my inner critic is like, overengineering much, Lara? Like, why are you it's just CSS, jeez. My god. But then I'm like, no. That's the kind of thinking that causes turd driven development. Say no to that. It's okay to think about CSS like this. And in fact like the rest of software has come up with many an antidote to turds. So, general software on this end is kind of like, whoa, look at all these things we do to control our code. To create better environments and develop better programming practices. And then on the other side we have frontend and UI that has a lot of these things as well. So, design systems, atomic design, progressive enhancement. Many a CSS architecture and naming convention. And maybe these things are not that different. So, there's a lot of the same concepts that bridge these these two kind of areas that could seem separate. But testing. I think we could do more of this. Okay. Conclusion. I'll tell a small story time. Okay. How the math hater became a programmer. This is me. 14 year old Lara in 2003. I hate math. Okay? I was a staunch math hater throughout my childhood. I loved art class and horses and llamas. But at the age of 14 I was starting to become a little bit anti llama and just kind of embarrassed about that. But I loved art class and horses and Green Day. Which I didn't put up there. 2009. A little bit larger Lara. I had some blond in my hair and glasses. I was in college. 20 years old? Art school and I had a weird idea for a video game and learned how to code. I had a lot of freedom in school and very supportive parents. And then fast forward to 2015. I had been working as a freelance developer for a while and I wrote this article for CSS Tricks. Tales of a non unicorn: A story about the trouble with job titles and descriptions. This was about a role, the UI engineer/interaction designer. And I was like, yes, this is totally my thing. CSS, maybe some design, some like UI oriented JavaScript. And in the interview they asked me FizzBuzz. And FizzBuzz, for anybody unfamiliar, is sort of this beginner's algorithms question. And in the interview I was like, what? Why would anybody do this? I had been so far removed from what this algorithm in computer as someone self taught from an art background. And after I wrote this article, which became a little bit viral, there was a post on Reddit. Designer applies for JS job, fails at FizzBuzz, then proceeds to write 5 page rant about job descriptions. I was like, whoa. This was on the front page. There were all these horrible comments coming into the article. Like, awful stuff. And sob, after this experience from like 2015 to 2017, I was like, oh, hell no. Like, I am not a programmer. Computer science is not what I do. I do HTML and CSS. Computer science, not for me. Programming, not what I do. Who are these people? No thanks. I had like these two years of rebellion against that kind of identity. And late 2017 I ended up getting an interview for a job I was super excited about that was going to be an algorithms interview. No question about it. Okay. I have to learn this. Swallow my pride, FizzBuzz, let's do it. I wrote all these blog posts and put myself through computer science boot camp. And I was like, wait a second, this is for me. This is cool. I love this stuff. And it's not so different than the concepts in HTML and CSS. And in 2018 I proposed this original talk of algorithms of CSS for CSS ConfEU to bridge the gap between CSS and computer science. And throughout that talk, CSS something I knew well before kind of went from like CSS to like, wow. I understand what CSS is doing. Like, this is freaking amazing. I love CSS. And I realized that this is kind of the wrong metaphor. It's not like this. It's like this. So, computer science is like the big like, you know, mom giving everyone a hug. All these nice things in here. So, CSS, they're all together. So, to put a button on this. Here is FizzBuzz in CSS. [ Applause ] Okay. Okay. 2019. Is blank a blank? Is CSS a programming language? This is like a fucked up question structure. Because you can sub out the terms and have like is depression a treatable illness? Is non binary a gender? When you ask a question like this, it's opening up the option for people to say no, when as soon as you start excluding something from something else, that's a sign of much darker stuff. So, this is a smelly question. This is a culture smell. The answer is, of course. So, I'm like, what is going on? Why is this happen something why are there designers designing systems at companies, but they can't have anybody from the engineering team implement them because HTML and CSS are not considered part of engineering? Or why are there developers coming from full stack bootcamps or presenting themselves as full stack developers who don't understand fundamental characteristics of CSS? Is CSS not part of the stack anymore? What's going on? I was describing this to someone at my coworking space, kind of an old school computer science guide. His name is Dick. And why are there so many people that don't think CSS is a programming language? What's going on? He said, well, Lara, when it comes to computer science, and in computer science, there's an 800 pound gorilla in the room and it's called a testosterone. And I was like, okay. Wow. Okay. So, maybe this is the truth. Is this what like, okay. But I don't think the answer is to not talk about it. So, when I see responses to this question, it's like, stop asking this question. Don't talk about it. Questions like that can be good because it brings out what we need to address. So, what if instead of, you know, people who know other types of programming not learning HTML and CSS because they're not programming. I know programming. I don't want to learn that, it's not my thing. And web applications suffering because of that. That's on one side. And we have people like me and I'm sure some people in this room who were focused in HTML and CSS and told you're not a real programmer. And therefore you develop this kind of oppositional identity, I'm not learning that. That was me. What if we do this, CSS and HTML are this little golden springboard. You have little people like me, little baby Lara, or people with non traditional backgrounds who don't necessarily have the ability to go into computer science programs, et cetera. HTML and CSS can be this kind of springboard into technology. And not just people that look like me. Of course, like anybody can do this. And it's also kind of a metaphor for creativity. Because I'm not that good at drawing people. I put a monster in it. It has to represent something. Creativity. Let's have more creativity and honor technology teams. HTML and CSS, this golden springboard. My question is, why aren't we valuing these skills more and embracing this technology? Instead of this is not for you, saying, yes, you are a programmer. Come, learn more. Thank you. [ Applause ] KATIE: Wow. Okay. Yes, yes. Yes, yes. Yes. You're awesome. Yes. I am so excited that we are going to lunch right now because I would feel really bad for anyone who had to follow that up. Thank you, Lara. That was amazing. Yeah. Thank you. [ Applause ] All right. So, it is lunchtime. Before you go, I have two things that I need to do. The first thing is that I need to tell you back in this room at 12:30 because folks have been so interested in learning more about how the closed captioning works, that Mux has sponsored a special presentation where the folks from White Coat are going to show us how their closed captioning works and how they transcribe things so quickly. And the second thing that I need to do, because my 8 year old daughter and my 6 year old son are in the back of the room is I need to tell you all a joke that my daughter told me. All right. So, why is a seagull called a seagull? Cause if it flew over a bay, it would be called a beagle. [ Applause ] All right. So, everyone go and enjoy your lunch and we'll see you back here or in the scythe HPE room when lunch is done. test this is test.
B1 中級 CSS算法--Lara Schenck--2019年美國JSConf大會。 (CSS Algorithms - Lara Schenck - JSConf US 2019) 2 1 林宜悉 發佈於 2021 年 01 月 14 日 更多分享 分享 收藏 回報 影片單字