{"id":288018,"date":"2019-05-30T08:07:10","date_gmt":"2019-05-30T15:07:10","guid":{"rendered":"http:\/\/css-tricks.com\/?p=288018"},"modified":"2019-05-31T08:02:28","modified_gmt":"2019-05-31T15:02:28","slug":"a-practical-use-case-for-vue-render-functions-building-a-design-system-typography-grid","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/a-practical-use-case-for-vue-render-functions-building-a-design-system-typography-grid\/","title":{"rendered":"A Practical Use Case for Vue Render Functions: Building a Design System Typography Grid"},"content":{"rendered":"

This post covers how I built a typography grid for a design system using Vue render functions<\/a>. Here\u2019s the demo<\/a> and the code<\/a>. I used render functions because they allow you to create HTML with a greater level of control than regular Vue templates, yet surprisingly I couldn\u2019t find very much when I web searched around for real-life, non-tutorial applications of them. I\u2019m hoping this post will fill that void and provide a helpful and practical use case on using Vue render functions.<\/p>\n

I\u2019ve always found render functions to be a little out-of-character for Vue. While the rest of the framework emphasizes simplicity and separation of concerns, render functions are a strange and often difficult-to-read mix of HTML and JavaScript. <\/p>\n

<\/p>\n

For example, to display: <\/p>\n

<div class=\"container\">\r\n  <p class=\"my-awesome-class\">Some cool text<\/p>\r\n<\/div><\/code><\/pre>\n

…you need:<\/p>\n

render(createElement) {\r\n  return createElement(\"div\", { class: \"container\" }, [\r\n    createElement(\"p\", { class: \"my-awesome-class\" }, \"Some cool text\")\r\n  ])\r\n}<\/code><\/pre>\n

I suspect that this syntax turns some people off, since ease-of-use is a key reason to reach for Vue in the first place. This is a shame because render functions and functional components are capable of some pretty cool, powerful stuff. In the spirit of demonstrating their value, here\u2019s how they solved an actual business problem for me. <\/p>\n

Quick disclaimer:<\/strong> It will be super helpful to have the demo<\/a> open in another tab to reference throughout this post.<\/p>\n

Defining criteria for a design system<\/h3>\n

My team wanted to include a page in our VuePress<\/a>-powered design system showcasing different typography options. This is part of a mockup that I got from our designer.<\/p>\n

\"A<\/figure>\n

And here\u2019s a sample of some of the corresponding CSS: <\/p>\n

h1, h2, h3, h4, h5, h6 {\r\n  font-family: \"balboa\", sans-serif;\r\n  font-weight: 300;\r\n  margin: 0;\r\n}\r\n\r\nh4 {\r\n  font-size: calc(1rem - 2px);\r\n}\r\n\r\n.body-text {\r\n  font-family: \"proxima-nova\", sans-serif;\r\n}\r\n\r\n.body-text--lg {\r\n  font-size: calc(1rem + 4px);\r\n}\r\n\r\n.body-text--md {\r\n  font-size: 1rem;\r\n}\r\n\r\n.body-text--bold {\r\n  font-weight: 700;\r\n}\r\n\r\n.body-text--semibold {\r\n  font-weight: 600;\r\n}<\/code><\/pre>\n

Headings are targeted with tag names. Other items use class names, and there are separate classes for weight and size. <\/p>\n

Before writing any code, I created some ground rules: <\/p>\n