Styling the app
→ Click here to see the state of the app after completing this step.
→ Click here to see the changes we'll make in this step in GitHub.
gg has a built in API that allows you to add CSS to your website in a safe and minimalistic way. You can pass a string to the function gg.stylesheet which contains valid CSS. Those styles will be optimised, minimised and automatically included in the markup of the compiled pages.
To add global styles to a page you can pass a second parameter to the gg.page function. This should be an object containing a property called stylesheet with the actual stylesheet as value. Let's use this and add some styles for the body element.
2 +3const stylesheet = gg.stylesheet(`+4 body {+5 margin: 0 auto;+6 max-width: 24rem;+7 font-family: sans-serif;+8 background-color: #F6F7F8;+9 }+10`); 11 ⋮ 57 -export const page = gg.page(PageComponent);+58export const page = gg.page(PageComponent, { stylesheet }); 59
Now let's start to style individual elements. We start with adding some styles for the calculator display, i.e. the element that contains the numbers, the operator and the calculation result.
9 }+10 .display {+11 font-size: 3em;+12 text-align: right;+13 padding: 0.1em 0.25em;+14 +15 min-height: 1.5em;+16 width: 24rem;+17 +18 border: 2px solid #7A8EA1;+19 box-sizing: border-box;+20 } 21`);
We also have to add the class to the HTML element. You might intuitively want to do this.
33 <p>Apply one basic arithmetic operation at a time to two numbers.</p>-<div>3 + 4</div>+34 <div class="display">3 + 4</div> 35 <div>
This won't work for two reasons. The class attribute does not contain only one value, but actually it contains multiple space-separated names of classes. gg mimics this behavior in its type definitions for the attribute by making it an array of strings instead of just one string. (If you got a TypeScript error after changing the above, it basically tries to tell you exactly that.)
33 <p>Apply one basic arithmetic operation at a time to two numbers.</p>-<div class="display">3 + 4</div>+34 <div class={["display"]}>3 + 4</div> 35 <div>
Now TypeScript is happy, but you still won't see any changes on the website. That is because gg minifies class names in order to make the size of the compiles html-file as small as possible.
In order to add the minified class name to your markup we have to use the getClass method provided by the stylesheet.
33 <p>Apply one basic arithmetic operation at a time to two numbers.</p>-<div class={["display"]}>3 + 4</div>+34 <div class={[stylesheet.getClass("display")]}>3 + 4</div> 35 <div>
Now we're talking! Let's also add some styles to the buttons.
20 }+21 .button {+22 padding: 0.25em 0;+23 background-color: #CBD3DB;+24 font-size: 2em;+25 border: 2px solid #7A8EA1;+26 border-top: none;+27 border-radius: 0;+28 width: 6rem;+29 } 30`); ⋮ 44 <div>-<button>AC</button>-<button>C</button>-<button>ANS</button>-<button>{"÷"}</button>+45 <button class={[stylesheet.getClass("button")]}>AC</button>+46 <button class={[stylesheet.getClass("button")]}>C</button>+47 <button class={[stylesheet.getClass("button")]}>ANS</button>+48 <button class={[stylesheet.getClass("button")]}>{"÷"}</button> 49 </div> 50 <div>-<button>7</button>-<button>8</button>-<button>9</button>-<button>{"×"}</button>+51 <button class={[stylesheet.getClass("button")]}>7</button>+52 <button class={[stylesheet.getClass("button")]}>8</button>+53 <button class={[stylesheet.getClass("button")]}>9</button>+54 <button class={[stylesheet.getClass("button")]}>{"×"}</button> 55 </div> 56 <div>-<button>4</button>-<button>5</button>-<button>6</button>-<button>-</button>+57 <button class={[stylesheet.getClass("button")]}>4</button>+58 <button class={[stylesheet.getClass("button")]}>5</button>+59 <button class={[stylesheet.getClass("button")]}>6</button>+60 <button class={[stylesheet.getClass("button")]}>-</button> 61 </div> 62 <div>-<button>1</button>-<button>2</button>-<button>3</button>-<button>+</button>+63 <button class={[stylesheet.getClass("button")]}>1</button>+64 <button class={[stylesheet.getClass("button")]}>2</button>+65 <button class={[stylesheet.getClass("button")]}>3</button>+66 <button class={[stylesheet.getClass("button")]}>+</button> 67 </div> 68 <div>-<button>0</button>-<button>.</button>-<button>=</button>+69 <button class={[stylesheet.getClass("button")]}>0</button>+70 <button class={[stylesheet.getClass("button")]}>.</button>+71 <button class={[stylesheet.getClass("button")]}>=</button> 72 </div>
It's also no problem at all to use more complex CSS selectors than just elements or classes. Let's make the buttons more interactive by adding some focus-, hover- and active-styles.
29 }+30 .button:hover {+31 background-color: #C7EAFF;+32 }+33 .button:focus {+34 outline: none;+35 border-color: #20A4F3;+36 box-shadow: -1px -1px 0 2px #20A4F3;+37 position: relative;+38 z-index: 1;+39 }+40 .button:focus:first-child {+41 box-shadow: 0px -2px 0 1px #20A4F3, 0px 0px 0 1px #20A4F3+42 }+43 .button:active {+44 background-color: #93D5FC;+45 } 46`);
We can use CSS sibling selectors to remove the left-border on all buttons except the first one.
45 }+46 .button + .button {+47 border-left: none;+48 } 49`);
At last we'll double the width of the zero-button so that the calculator does not have a "hole" in the bottom right corner.
48 }+49 .double-width {+50 width: 12rem;+51 } 52`); ⋮ 90 <div>-<button class={[stylesheet.getClass("button")]}>0</button>+91 <button+92 class={[+93 stylesheet.getClass("button"),+94 stylesheet.getClass("double-width"),+95 ]}+96 >+97 0+98 </button> 99 <button class={[stylesheet.getClass("button")]}>.</button>
Now isn't that some good-lookin' calculator! Next up we'll learn how we can use components in gg to encapsulate markup and avoid duplication.
Next → Using components