<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Python GUIs - css</title><link href="https://www.pythonguis.com/" rel="alternate"/><link href="https://www.pythonguis.com/feeds/css.tag.atom.xml" rel="self"/><id>https://www.pythonguis.com/</id><updated>2021-02-15T09:00:00+00:00</updated><subtitle>Create GUI applications with Python and Qt</subtitle><entry><title>CSS Selector for widget Class — How to use Qt property selectors in stylesheets to target widgets by custom class</title><link href="https://www.pythonguis.com/faq/css-selector-for-widget-class/" rel="alternate"/><published>2021-02-15T09:00:00+00:00</published><updated>2021-02-15T09:00:00+00:00</updated><author><name>Martin Fitzpatrick</name></author><id>tag:www.pythonguis.com,2021-02-15:/faq/css-selector-for-widget-class/</id><summary type="html">I've set a custom property on a widget using &lt;code&gt;setProperty("cssClass", "welcome")&lt;/code&gt; and I'm trying to select and style this widget from my stylesheet, but it's not working. What am I doing wrong?</summary><content type="html">
            &lt;blockquote&gt;
&lt;p&gt;I've set a custom property on a widget using &lt;code&gt;setProperty("cssClass", "welcome")&lt;/code&gt; and I'm trying to select and style this widget from my stylesheet, but it's not working. What am I doing wrong?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Qt stylesheets support property selectors that let you target widgets based on custom properties &amp;mdash; this is a great way to apply styles to specific groups of widgets without subclassing. However, there are a couple of common stumbling blocks that can prevent it from working. Let's walk through how to get this right.&lt;/p&gt;
&lt;h2 id="the-property-selector-syntax"&gt;The property selector syntax&lt;/h2&gt;
&lt;p&gt;In Qt stylesheets, you can select widgets by their properties using square bracket notation, similar to CSS attribute selectors. The general form looks like this:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-css"&gt;css&lt;/span&gt;
&lt;pre&gt;&lt;code class="css"&gt;QWidget[propertyName="value"] {
    /* styles go here */
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;If you've set a property on a widget like this:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
&lt;pre&gt;&lt;code class="python"&gt;widget.setProperty("cssClass", "welcome")
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Then the matching selector in your stylesheet would be:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-css"&gt;css&lt;/span&gt;
&lt;pre&gt;&lt;code class="css"&gt;QWidget[cssClass="welcome"] {
    background-color: #3498db;
    color: white;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;h2 id="a-missing-closing-quote"&gt;A missing closing quote&lt;/h2&gt;
&lt;p&gt;Looking at the original attempt, there's a small but significant typo &amp;mdash; the closing double quote around the property value is missing:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-css"&gt;css&lt;/span&gt;
&lt;pre&gt;&lt;code class="css"&gt;/* ❌ Missing closing quote */
QWidget[cssClass="welcome] {

}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;It should be:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-css"&gt;css&lt;/span&gt;
&lt;pre&gt;&lt;code class="css"&gt;/* ✅ Correct */
QWidget[cssClass="welcome"] {

}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;That missing &lt;code&gt;"&lt;/code&gt; after &lt;code&gt;welcome&lt;/code&gt; is enough to make the entire selector invalid, so no styles will be applied.&lt;/p&gt;
&lt;h2 id="applying-stylesheets-after-setting-properties"&gt;Applying stylesheets after setting properties&lt;/h2&gt;
&lt;p&gt;One thing to be aware of: Qt evaluates stylesheet selectors against widget properties at the time the stylesheet is applied. If you set a property &lt;em&gt;after&lt;/em&gt; the stylesheet has already been applied, the widget may not pick up the new style automatically.&lt;/p&gt;
&lt;p&gt;To handle this, you can either:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Set the property &lt;strong&gt;before&lt;/strong&gt; applying the stylesheet.&lt;/li&gt;
&lt;li&gt;Call &lt;code&gt;unpolish&lt;/code&gt; and &lt;code&gt;polish&lt;/code&gt; on the widget's style to force a re-evaluation after changing a property.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here's how you'd force a style refresh:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
&lt;pre&gt;&lt;code class="python"&gt;widget.setProperty("cssClass", "welcome")
widget.style().unpolish(widget)
widget.style().polish(widget)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;This tells Qt to re-evaluate the stylesheet rules for that widget with its current properties.&lt;/p&gt;
&lt;h2 id="a-complete-working-example"&gt;A complete working example&lt;/h2&gt;
&lt;p&gt;Here's a full example that creates two labels &amp;mdash; one with a custom &lt;code&gt;cssClass&lt;/code&gt; property and one without &amp;mdash; so you can see the property selector in action. If you're new to building interfaces with PyQt6, you may want to start with the &lt;a href="https://www.pythonguis.com/tutorials/pyqt6-creating-your-first-window/"&gt;creating your first window&lt;/a&gt; tutorial first.&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
&lt;pre&gt;&lt;code class="python"&gt;import sys
from PyQt6.QtWidgets import (
    QApplication, QWidget, QLabel, QVBoxLayout
)


app = QApplication(sys.argv)

# Define the stylesheet with a property selector.
app.setStyleSheet("""
    QLabel[cssClass="welcome"] {
        background-color: #2ecc71;
        color: white;
        font-size: 18px;
        padding: 10px;
        border-radius: 5px;
    }
    QLabel[cssClass="warning"] {
        background-color: #e74c3c;
        color: white;
        font-size: 18px;
        padding: 10px;
        border-radius: 5px;
    }
    QLabel {
        font-size: 14px;
        padding: 5px;
    }
""")

window = QWidget()
window.setWindowTitle("Property Selector Demo")
layout = QVBoxLayout()

# This label will match the [cssClass="welcome"] selector.
welcome_label = QLabel("Welcome! This label has cssClass='welcome'")
welcome_label.setProperty("cssClass", "welcome")

# This label will match the [cssClass="warning"] selector.
warning_label = QLabel("Watch out! This label has cssClass='warning'")
warning_label.setProperty("cssClass", "warning")

# This label has no custom property, so only the generic QLabel style applies.
plain_label = QLabel("This is a plain label with no custom property.")

layout.addWidget(welcome_label)
layout.addWidget(warning_label)
layout.addWidget(plain_label)

window.setLayout(layout)
window.show()

sys.exit(app.exec())
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;When you run this, you'll see three labels: a green one styled by the &lt;code&gt;welcome&lt;/code&gt; selector, a red one styled by the &lt;code&gt;warning&lt;/code&gt; selector, and a plain one that only picks up the default &lt;code&gt;QLabel&lt;/code&gt; style. The example uses a &lt;a href="https://www.pythonguis.com/tutorials/pyqt6-layouts/"&gt;QVBoxLayout&lt;/a&gt; to arrange the labels vertically.&lt;/p&gt;
&lt;h2 id="loading-styles-from-an-external-file"&gt;Loading styles from an external file&lt;/h2&gt;
&lt;p&gt;If you prefer to keep your styles in a separate &lt;code&gt;.css&lt;/code&gt; file (which is a good idea for larger applications), you can load the file and apply it like this:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-python"&gt;python&lt;/span&gt;
&lt;pre&gt;&lt;code class="python"&gt;with open("style.css", "r") as f:
    app.setStyleSheet(f.read())
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Your &lt;code&gt;style.css&lt;/code&gt; file would then contain the same stylesheet rules:&lt;/p&gt;
&lt;div class="code-block"&gt;
&lt;span class="code-block-language code-block-css"&gt;css&lt;/span&gt;
&lt;pre&gt;&lt;code class="css"&gt;QLabel[cssClass="welcome"] {
    background-color: #2ecc71;
    color: white;
    font-size: 18px;
    padding: 10px;
    border-radius: 5px;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Just make sure the file path is correct relative to where you're running your script, or use an absolute path. For larger projects, you might also want to consider using the &lt;a href="https://www.pythonguis.com/tutorials/pyside6-qresource-system/"&gt;Qt Resource system&lt;/a&gt; to bundle your stylesheet files with your application.&lt;/p&gt;
&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;
&lt;p&gt;Custom property selectors are a flexible way to style specific widgets in Qt without creating subclasses or applying inline styles everywhere. If you need even more control over widget appearance, you can also &lt;a href="https://www.pythonguis.com/tutorials/pyqt6-creating-your-own-custom-widgets/"&gt;create your own custom widgets&lt;/a&gt;. Keep these points in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The syntax is &lt;code&gt;QWidget[property="value"]&lt;/code&gt; &amp;mdash; make sure both quotes are present.&lt;/li&gt;
&lt;li&gt;Set properties &lt;strong&gt;before&lt;/strong&gt; the stylesheet is applied, or use &lt;code&gt;unpolish&lt;/code&gt;/&lt;code&gt;polish&lt;/code&gt; to refresh the style after changing a property.&lt;/li&gt;
&lt;li&gt;You can use any property name you like &amp;mdash; &lt;code&gt;cssClass&lt;/code&gt; is a perfectly fine convention, but you could equally use &lt;code&gt;role&lt;/code&gt;, &lt;code&gt;category&lt;/code&gt;, or anything else that makes sense for your application.&lt;/li&gt;
&lt;/ul&gt;
            &lt;p&gt;For an in-depth guide to building Python GUIs with PyQt6 see my book, &lt;a href="https://www.martinfitzpatrick.com/pyqt6-book/"&gt;Create GUI Applications with Python &amp; Qt6.&lt;/a&gt;&lt;/p&gt;
            </content><category term="pyqt6"/><category term="pyqt"/><category term="stylesheets"/><category term="css"/><category term="python"/><category term="qt"/><category term="qt6"/></entry></feed>