Skip to content

CSS Reference

PyWry provides a comprehensive CSS system with theme support, CSS variables, and utility classes.

Theme Classes

Apply to root element or widget container:

Class Description
.pywry-theme-dark Dark theme (default)
.pywry-theme-light Light theme
.pywry-theme-system Follow OS preference
<div class="pywry-widget pywry-theme-dark">
  <!-- Dark themed content -->
</div>

CSS Variables

Typography

:root {
    --pywry-font-family: Inter, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --pywry-font-size: 14px;
    --pywry-font-weight-normal: 400;
    --pywry-font-weight-medium: 500;
}

Spacing & Layout

:root {
    --pywry-radius: 4px;
    --pywry-radius-lg: 6px;
    --pywry-spacing-xs: 2px;
    --pywry-spacing-sm: 4px;
    --pywry-spacing-md: 6px;
    --pywry-spacing-lg: 8px;
}

Widget Sizing

:root {
    --pywry-widget-width: 100%;
    --pywry-widget-min-height: 200px;
    --pywry-widget-height: 500px;
    --pywry-grid-min-height: 200px;
}

Transitions

:root {
    --pywry-transition-fast: 0.1s ease;
    --pywry-transition-normal: 0.2s ease;
}

Accent Colors (Shared)

:root {
    --pywry-accent: #0078d4;
    --pywry-accent-hover: #106ebe;
    --pywry-text-accent: rgb(51, 187, 255);
    --pywry-btn-neutral-bg: rgb(0, 136, 204);
    --pywry-btn-neutral-text: #ffffff;
    --pywry-btn-neutral-hover: rgb(0, 115, 173);
}

Dark Theme Colors

.pywry-theme-dark {
    --pywry-bg-primary: #212124;
    --pywry-bg-secondary: rgba(21, 21, 24, 1);
    --pywry-bg-tertiary: rgba(31, 30, 35, 1);
    --pywry-bg-quartary: rgba(36, 36, 42, 1);
    --pywry-bg-hover: rgba(255, 255, 255, 0.08);
    --pywry-bg-overlay: rgba(30, 30, 30, 0.8);
    --pywry-text-primary: #ebebed;
    --pywry-text-secondary: #a0a0a0;
    --pywry-text-muted: #707070;
    --pywry-border-color: #333;
    --pywry-border-focus: #555;

    /* Tab Group */
    --pywry-tab-bg: #2a2a2e;
    --pywry-tab-active-bg: #3d3d42;
    --pywry-tab-hover-bg: #353538;

    /* Buttons */
    --pywry-btn-primary-bg: #e2e2e2;
    --pywry-btn-primary-text: #151518;
    --pywry-btn-primary-hover: #cccccc;
    --pywry-btn-secondary-bg: #3d3d42;
    --pywry-btn-secondary-text: #ebebed;
    --pywry-btn-secondary-hover: #4a4a50;
    --pywry-btn-secondary-border: rgba(90, 90, 100, 0.5);
}

Light Theme Colors

.pywry-theme-light {
    --pywry-bg-primary: #f5f5f5;
    --pywry-bg-secondary: #ffffff;
    --pywry-bg-hover: rgba(0, 0, 0, 0.06);
    --pywry-bg-overlay: rgba(255, 255, 255, 0.8);
    --pywry-text-primary: #000000;
    --pywry-text-secondary: #666666;
    --pywry-text-muted: #999999;
    --pywry-border-color: #ccc;
    --pywry-border-focus: #999;

    /* Tab Group */
    --pywry-tab-bg: #e8e8ec;
    --pywry-tab-active-bg: #ffffff;
    --pywry-tab-hover-bg: #f0f0f4;

    /* Buttons */
    --pywry-btn-primary-bg: #2c2c32;
    --pywry-btn-primary-text: #ffffff;
    --pywry-btn-primary-hover: #1a1a1e;
    --pywry-btn-secondary-bg: #d0d0d8;
    --pywry-btn-secondary-text: #2c2c32;
    --pywry-btn-secondary-hover: #c0c0c8;
    --pywry-btn-secondary-border: rgba(180, 180, 190, 1);
}

Layout Classes

Container

.pywry-widget {
    /* Main widget container */
    width: var(--pywry-widget-width);
    min-height: var(--pywry-widget-min-height);
    height: var(--pywry-widget-height);
    display: flex;
    flex-direction: column;
}

.pywry-container {
    /* Content container */
    flex: 1 1 0%;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

Toolbar Positions

.pywry-toolbar { /* Base toolbar */ }
.pywry-toolbar-top { /* Top position */ }
.pywry-toolbar-bottom { /* Bottom position */ }
.pywry-toolbar-left { /* Left sidebar */ }
.pywry-toolbar-right { /* Right sidebar */ }
.pywry-toolbar-header { /* Header with bottom border */ }
.pywry-toolbar-footer { /* Footer with top border */ }
.pywry-toolbar-inside { /* Floating overlay */ }

Toolbar Content

.pywry-toolbar-content {
    /* Flex container for toolbar items */
    display: flex;
    flex-wrap: wrap;
    gap: var(--pywry-spacing-md);
    align-items: center;
}

Component Classes

Buttons

.pywry-btn { /* Base button */ }
.pywry-btn-primary { /* Primary style */ }
.pywry-btn-secondary { /* Secondary style */ }
.pywry-btn-neutral { /* Blue neutral style */ }
.pywry-btn-danger { /* Red danger style */ }
.pywry-btn-success { /* Green success style */ }
.pywry-btn-sm { /* Small size */ }
.pywry-btn-md { /* Medium size (default) */ }
.pywry-btn-lg { /* Large size */ }

Inputs

.pywry-input { /* Base input */ }
.pywry-input-group { /* Label + input wrapper */ }
.pywry-input-label { /* Input label */ }
.pywry-select { /* Select dropdown */ }
.pywry-textarea { /* Textarea */ }
.pywry-input-secret { /* Password input */ }

Toggle & Checkbox

.pywry-toggle { /* Toggle switch */ }
.pywry-toggle-track { /* Toggle track */ }
.pywry-toggle-thumb { /* Toggle thumb */ }
.pywry-checkbox { /* Checkbox wrapper */ }
.pywry-checkbox-input { /* Checkbox input */ }
.pywry-checkbox-label { /* Checkbox label */ }

Tabs

.pywry-tab-group { /* Tab container */ }
.pywry-tab { /* Individual tab */ }
.pywry-tab.active { /* Active tab */ }

Slider

.pywry-slider { /* Slider wrapper */ }
.pywry-slider-input { /* Range input */ }
.pywry-slider-value { /* Value display */ }

Marquee

.pywry-marquee { /* Scrolling container */ }
.pywry-marquee-track { /* Animated track */ }
.pywry-marquee-content { /* Content wrapper */ }
.pywry-marquee-left { /* Scroll left */ }
.pywry-marquee-right { /* Scroll right */ }
.pywry-marquee-up { /* Scroll up */ }
.pywry-marquee-down { /* Scroll down */ }
.pywry-marquee-static { /* No animation */ }
.pywry-marquee-pause { /* Pause on hover */ }
.pywry-ticker-item { /* Ticker item */ }

Divs

.pywry-div { /* Div component */ }

State Classes

.pywry-disabled { /* Disabled state */ }
.pywry-collapsed { /* Collapsed toolbar */ }
.pywry-loading { /* Loading state */ }

Scrollbar Classes

Custom scrollbars for native windows:

.pywry-scroll-wrapper { /* Scroll container wrapper */ }
.pywry-scroll-container { /* Scrollable content */ }
.pywry-scrollbar-track-v { /* Vertical scrollbar track */ }
.pywry-scrollbar-track-h { /* Horizontal scrollbar track */ }
.pywry-scrollbar-thumb-v { /* Vertical scrollbar thumb */ }
.pywry-scrollbar-thumb-h { /* Horizontal scrollbar thumb */ }

Native Window Classes

Applied to <html> element in Tauri windows:

html.pywry-native { /* Native window context */ }
html.dark { /* Dark mode on html */ }
html.light { /* Light mode on html */ }

Custom CSS Injection

Inject CSS at runtime via Python:

# In a callback (using app.emit with label)
def on_apply_styles(data, event_type, label):
    app.emit("pywry:inject-css", {
        "id": "my-custom-styles",
        "css": """
            .my-class {
                color: var(--pywry-text-accent);
                background: var(--pywry-bg-secondary);
            }
        """
    }, label)

# Or with a widget handle
widget = app.show("<h1>Demo</h1>")
widget.emit("pywry:inject-css", {
    "id": "my-custom-styles",
    "css": ".highlight { background: yellow; }"
})

Remove injected CSS:

app.emit("pywry:remove-css", {"id": "my-custom-styles"}, label)

Inline Styles

Set inline styles via Python:

# By element ID
app.emit("pywry:set-style", {
    "id": "my-element",
    "styles": {
        "fontSize": "24px",
        "fontWeight": "bold",
        "color": "red"
    }
}, label)

# By CSS selector
app.emit("pywry:set-style", {
    "selector": ".my-class",
    "styles": {"display": "none"}
}, label)

Override Examples

Custom Widget Height

from pywry import PyWry

app = PyWry(
    html="<h1>Tall Widget</h1>",
    head="""
    <style>
        :root {
            --pywry-widget-height: 800px;
        }
    </style>
    """
)

Custom Theme

custom_css = """
<style>
    .pywry-theme-custom {
        --pywry-bg-primary: #1a1a2e;
        --pywry-bg-secondary: #16213e;
        --pywry-text-primary: #e94560;
        --pywry-accent: #0f3460;
    }
</style>
"""

app = PyWry(html=content, head=custom_css)

Custom Button Styles

from pywry import PyWry, Toolbar, Button

app = PyWry()

def on_customize(data, event_type, label):
    app.emit("pywry:inject-css", {
        "id": "custom-buttons",
        "css": """
            .pywry-btn-primary {
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                border: none;
            }
            .pywry-btn-primary:hover {
                background: linear-gradient(135deg, #764ba2 0%, #667eea 100%);
            }
        """
    }, label)

app.show(
    "<h1>Styled Buttons</h1>",
    toolbars=[Toolbar(position="top", items=[Button(label="Customize", event="ui:customize", variant="primary")])],
    callbacks={"ui:customize": on_customize},
)

AG Grid Theme Integration

PyWry automatically syncs AG Grid themes:

/* Dark mode */
.ag-theme-quartz-dark { /* Applied automatically */ }

/* Light mode */
.ag-theme-quartz { /* Applied automatically */ }

Update theme via event:

# In a callback
app.emit("pywry:update-theme", {"theme": "light"}, label)