Loading video player…

Styling With TCSS

00:00 In the previous lesson, I showed you how to style text widgets using the styles property. In this lesson, I’ll show you the power of Textual’s CSS mechanism.

00:10 Textual supports a subset of the cascading style sheet interface used to style web pages. They call the subset TCSS. Although I do a lot of web development, I’m not really a fan of CSS.

00:23 It feels like a Jenga tower of hacks to me, with each release trying to compensate for the fact that the last release didn’t fully compensate for the one before it.

00:32 Textual’s use of CSS is why it took me a while to even try it out, but the library builders have chosen the right parts of CSS. In the previous lesson, you saw how to use the styles property to individually change a widget, but by using CSS, you can achieve the same thing with far less code.

00:49 Like with the web, you can specify CSS separately from the components, and then the styles get applied to your widgets. You can specify style rules based on the Python class of the widget, the ID associated with a widget instance, or by creating a CSS class with a string.

01:08 The first and last example of these mean you can create styles that are consistent across your interface for multiple widgets. For example, changing all buttons or all of the widgets with a certain CSS class label.

01:22 One of the things I still don’t like about CSS is debugging it. I never seem to get the layout right the first time. Textual helps with this as well. So far, you’ve been running your apps directly from Python, but you can also use the textual command to run them instead. If you do and use the --dev flag, Textual will update the interface on the fly while you edit the CSS.

01:47 You don’t have to exit and restart the program. You simply make the change and watch its effects. To use this feature, you need a separate library, textual-dev, you pip install it like any other, and once you have, you can invoke your app either with Python directly or through the textual run command like I’m showing here.

02:07 Let’s go write another Textual app, this time using CSS to style it.

02:13 I’m still sticking with Static widgets, but this time I’m going to style them with CSS. There are several ways of associating TCSS with your app.

02:22 The one I’m using here is setting the CSS_PATH class property, giving it the name of the file where I’m going to define my CSS rules. Like before, I’m yielding components.

02:34 This one being a vanilla static object, and here I’m yielding another one, but this time I’ve set the id argument. Now this object can be associated with id-based CSS rules. Here instead, I’m declaring a CSS class.

02:52 You do that with the classes argument, which takes a string. This object will respond to CSS class rules named static_cls1. A widget can have multiple CSS classes.

03:04 You do that by passing in a space delimited string. This object has both the static_cls1 class like the one above it, and a static_cls2 as well.

03:16 Now let’s look at the associated TCSS file.

03:22 A CSS file is comprised of rules. You start by specifying what objects the rules apply to. Here, the capital S Static means this style applies to all widgets of that type.

03:34 You then use brace brackets to denote the block of style properties to apply to objects that meet this rule. All of our Static widgets will have a blue background and one line in character of padding around them.

03:47 The hash mark, also known as octothorpe, if you’re not on a first name basis, indicates an id. So #static with id means apply this rule to the widget that has this id.

04:00 And the style I want to apply to the object is to give it a white border. A period means this rule applies to a CSS class. All objects with this CSS class get these rules.

04:13 The C in CSS stands for cascading, which in this case means a sort of inheritance. The widget that this class applies to is also a Static widget, so the top rule and this rule will apply.

04:27 The rule about an object’s CSS class takes precedence over the rule about the Python class. So objects of this CSS type have the background property of blue overwritten to become green.

04:39 You’ll recall that one of our widgets has both of our CSS classes applied. So that one will have both a green background from the other class rule and a dashed yellow border from this one.

04:52 Let me fire this up in a terminal so you can take a look.

04:57 Okay, I’ve got my editor open on the left. Now let me run the app using the --dev flag.

05:07 As you can see, our four widgets have four different styles. This static CSS rule applies to all of the widgets, making this widget and this widget have a blue background.

05:19 The other two don’t because other rules override it.

05:24 Our third and fourth widgets have the static_class1 CSS class applied, which is what overrides the blue and turns them green. The fourth widget also has the static_cls2 applied, which is what gives you the yellow border.

05:40 Since I ran this app using the Textual run command in dev mode, I can live edit this style sheet.

05:52 As soon as I save this,

05:54 the app on the right-hand side gets updated. This is great for debugging. A very common trick when you’re trying to figure out if rules are getting applied is to add a red border around the thing you’re trying to debug.

06:07 This often also makes the padding and the margins clearer as well. By being able to do it live, you can muck around until you understand what is going on and make whatever fixes you want.

06:20 So far, you’ve only seen widgets that do nothing. In the next lesson, I’ll show you a couple of widgets with which your user can interact.

Become a Member to join the conversation.