---
title: "Compute CSS styles for an element"
url: https://recursiveai.org/onehtml/cookbook/computed-style-csharp/
description: "Get the computed value of any CSS property for an element, find the rule it came from, and recompute styles for a focused element or a narrow viewport…"
version: "1.0.0"
---

# Compute CSS styles for an element

Get the computed value of any CSS property for an element, find the rule it came from, and recompute styles for a focused element or a narrow viewport, including stylesheets the page links to.

`DocumentStyles.Create` gathers a page’s style sources and runs the cascade. That includes the HTML user-agent stylesheet, presentational attributes, `<style>`, `style=""` and linked sheets, with layers, `!important`, `var()`, shorthands and `@media`/`@supports`. The library never fetches anything, so a `<link rel=stylesheet>` gets its bytes from a resolver you supply, keyed by absolute URL.

The page in this example links `/css/site.css`:

```css
body { font-family: Georgia, serif; color: #222 }
.card h2 { font-size: 1.5rem }
nav ul { display: flex; gap: 1rem }
@media (max-width: 600px) {
  nav ul { display: block }
}
```

```csharp
using System.Text;
using RecursiveAI.OneHtml;
using RecursiveAI.OneHtml.Css;

Document doc = Document.Parse(File.ReadAllBytes("events.html"));

// The page links /css/site.css. The library never fetches it: you hand it the bytes.
var options = new StyleSourceOptions
{
    BaseUrl = "https://library.example/events/",
    Resolver = url => url == "https://library.example/css/site.css"
        ? new StylesheetResource(File.ReadAllBytes("site.css"))
        : null,
};
DocumentStyles styles = DocumentStyles.Create(doc, StyleContext.Default, options);

Node heading = doc.Root.QuerySelector(".card h2");
ComputedStyle style = styles.GetStyle(heading);
Console.WriteLine($"color: {style.GetPropertyValue("color")}, computed: {style.GetComputedValue("color")}");
Console.WriteLine($"font-size: {style.FontSizePx}px, display: {style.GetPropertyValue("display")}");

// Where a value came from
DeclarationSource? source = style.GetSource("color");
Console.WriteLine($"color set by \"{source?.SelectorText}\" in {source?.SheetUrl ?? "an inline <style>"}");
DeclarationSource? font = style.GetSource("font-family");
Console.WriteLine($"font-family: {style.GetPropertyValue("font-family")} from \"{font?.SelectorText}\" in {font?.SheetUrl}");

// The same element under another context: a focused link, a narrow viewport
Node link = doc.Root.QuerySelector("main a");
DocumentStyles focused = styles.WithContext(StyleContext.Default.WithFocus(link));
Console.WriteLine($"outline normally: {styles.GetStyle(link).GetPropertyValue("outline-style")}, " +
                  $"focused: {focused.GetStyle(link).GetPropertyValue("outline-style")}");

DocumentStyles phone = styles.WithContext(StyleContext.Default.WithMedia(new MediaFeatures { Width = 390, Height = 844 }));
Node nav = doc.Root.QuerySelector("nav ul");
Console.WriteLine($"nav at {MediaFeatures.Default.Width}px: {styles.GetStyle(nav).GetPropertyValue("display")}, " +
                  $"at 390px: {phone.GetStyle(nav).GetPropertyValue("display")}");

foreach (StyleDiagnostic diagnostic in styles.Diagnostics)
{
    Console.WriteLine(diagnostic);
}
```

```text
color: #1a4d7a, computed: rgb(26, 77, 122)
font-size: 24px, display: block
color set by ".card h2" in an inline <style>
font-family: Georgia, serif from "body" in https://library.example/css/site.css
outline normally: none, focused: solid
nav at 1280px: flex, at 390px: block
```

How to read it:

- `GetPropertyValue` returns the value as text. `GetComputedValue` returns the `getComputedStyle` serialization for the typed properties, such as colors as `rgb()`. Typed accessors such as `Color`, `FontSizePx`, `Display`, `Visibility` and `Opacity` give values you can compute with: `1.5rem` became `24px`.
- `GetSource` names the declaration that won: its selector, sheet URL (null for an inline `<style>`), origin, layer and importance. For an inherited property it is the ancestor’s declaration, here `body` in `site.css`.
- `StyleContext` is the environment: the viewport and media features, plus at most one focused, hovered, active or target element. `WithContext` returns a view that recomputes only what the new context can reach. The default viewport is 1280 px wide.
- `Diagnostics` reports what couldn’t be used, such as a linked sheet your resolver returned null for (`MissingStylesheet`), an import cycle or an unsupported rule. This page has none.

There is no layout. Values that depend on layout, like percentages resolved against a containing block or the used width of an element, stay unresolved. [Cascade](https://recursiveai.org/onehtml/docs/cascade/) lists what is implemented and what isn’t, and [CSS values](https://recursiveai.org/onehtml/docs/css-values/) lists the typed properties.
