loading
Note:
Extension methods, not a service Unlike most Butil APIs there is no Element class to inject. Capture any rendered element with @ref and the extension methods light up on the ElementReference itself. Only the event subscription and observer extensions additionally need an IJSRuntime argument.

Attributes

GetAttribute / SetAttribute / HasAttribute / ToggleAttribute / RemoveAttribute / GetAttributeNames

Read, write, toggle and enumerate the attributes of the target element. ToggleAttribute is handy for boolean attributes such as hidden or disabled; pass force to pin the state instead of flipping it.

Razor
<div @ref="box" data-demo="butil">...</div>

@code {
    private ElementReference box;

    private async Task InspectAttributes()
    {
        var has = await box.HasAttribute("data-demo");
        var value = await box.GetAttribute("data-demo");
        var names = await box.GetAttributeNames();

        await box.SetAttribute("data-demo", "updated");
        await box.ToggleAttribute("hidden", force: null);
        await box.RemoveAttribute("data-demo");
    }
}
Live sample
I am this section's target element.
Attribute name
Attribute value
attributes output
Results will appear here when you interact with the samples.

Scrolling

Scroll / ScrollBy / ScrollIntoView

Scroll inside an element to absolute coordinates, scroll by a relative amount, or bring the element itself into the viewport. All three accept an options object with smooth, instant or auto behavior; ScrollIntoView additionally takes block and inline logical positions.

Razor
<div @ref="box" style="overflow:auto; max-height:12rem">...</div>

@code {
    private ElementReference box;

    private async Task Scroll()
    {
        await box.Scroll(new ScrollOptions { Top = 120, Behavior = ScrollBehavior.Smooth });

        await box.ScrollBy(0, 48);

        await box.ScrollIntoView(new ScrollIntoViewOptions
        {
            Behavior = ScrollBehavior.Smooth,
            Block = ScrollLogicalPosition.Center,
            Inline = ScrollLogicalPosition.Nearest,
        });
    }
}
Live sample
This box is 40rem tall on the inside - use the buttons below to scroll it from C#.
scrolling output
Results will appear here when you interact with the samples.

Layout metrics

GetBoundingClientRect / Client* / Offset* / Scroll* / GetTagName

Read the element's box-model geometry: the viewport-relative bounding rect, client sizes (padding box), offset sizes (border box and position within the offset parent), scroll sizes and offsets, and the tag name.

Razor
<div @ref="box">...</div>

@code {
    private ElementReference box;

    private async Task Measure()
    {
        var rect = await box.GetBoundingClientRect(); // Rect { X, Y, Width, Height }

        var clientWidth = await box.GetClientWidth();
        var offsetHeight = await box.GetOffsetHeight();
        var scrollHeight = await box.GetScrollHeight();
        var scrollTop = await box.GetScrollTop();
        var tagName = await box.GetTagName();
    }
}
Live sample

The box being measured. It scrolls, so the scroll metrics have something to report.

Its padding box, border box and scroll box are all different sizes.

Scroll it and read the offsets back.

One more line, to make sure it overflows.

layout metrics output
Results will appear here when you interact with the samples.

Focus and pointer capture

Blur / SetPointerCapture / HasPointerCapture / ReleasePointerCapture / RequestPointerLock

Blur removes keyboard focus from an element (for setting focus, Blazor's built-in ElementReference.FocusAsync already covers it). Pointer capture routes all subsequent pointer events to one element - the building block for custom drag interactions. RequestPointerLock hides the cursor and streams raw movement deltas, as games do.

Razor
<input @ref="input" />
<div @ref="box" @onpointerdown="Capture">...</div>

@code {
    private ElementReference box;
    private ElementReference input;

    private async Task Capture(PointerEventArgs args)
    {
        await input.Blur();

        // The id comes from the pointer event that started the gesture - capture is per pointer.
        await box.SetPointerCapture(args.PointerId);
        var captured = await box.HasPointerCapture(args.PointerId);
        await box.ReleasePointerCapture(args.PointerId);

        // Needs a user gesture, and the browser shows its own notice on the way in.
        await box.RequestPointerLock();
    }
}
Live sample
Focus this input, then press the Blur button
Click me to record a pointer id, then capture and release it.

Pointer id: click this section's box first

focus and pointer output
Results will appear here when you interact with the samples.

Fullscreen

RequestFullScreen

Ask the browser to present the element fullscreen. The options object controls whether the browser keeps its navigation UI visible; press Escape to leave fullscreen again. Browsers only honor the request from a user gesture such as a click.

Razor
<div @ref="box">...</div>
<button @onclick="GoFullScreen">Full screen</button>

@code {
    private ElementReference box;

    // Must run inside a user gesture: a request that did not come from one is refused.
    private async Task GoFullScreen() =>
        await box.RequestFullScreen(new FullScreenOptions
        {
            NavigationUI = FullScreenNavigationUI.Show,
        });
}
Live sample
This panel goes fullscreen.
fullscreen output
Results will appear here when you interact with the samples.

Content and identity

Id / ClassName / InnerHtml / OuterHtml / InnerText / AccessKey / TabIndex

Get and set the element's id, class list, rendered text, raw markup, access key and tab order position. The InnerHtml and OuterHtml setters write markup verbatim - never feed them untrusted input.

Razor
<div @ref="box">...</div>

@code {
    private ElementReference box;

    private async Task Rewrite()
    {
        await box.SetId("hero");
        await box.SetClassName("card highlighted");
        await box.SetInnerText("Hello from C#");
        await box.SetTabIndex(2);
        await box.SetAccessKey("k");

        var html = await box.GetInnerHtml();
        await box.SetInnerHtml("<strong>Trusted markup only!</strong>");
        var outer = await box.GetOuterHtml();
    }
}
Live sample
Id
ClassName
InnerText
This element's id, class, text and markup are what the buttons below read and write.
content and identity output
Results will appear here when you interact with the samples.

Editing and interaction modes

ContentEditable / IsContentEditable / Dir / EnterKeyHint / InputMode / Hidden / Inert

Toggle in-place editing, text direction, virtual-keyboard hints, visibility and inertness on the target element. After setting ContentEditable to True, click into this section's box and type.

Razor
<div @ref="box">...</div>

@code {
    private ElementReference box;

    private async Task SetModes()
    {
        await box.SetContentEditable(ContentEditable.True);
        var editable = await box.IsContentEditable();

        await box.SetDir(ElementDir.Rtl);
        await box.SetEnterKeyHint(EnterKeyHint.Send);
        await box.SetInputMode(InputMode.Numeric);
        await box.SetHidden(Hidden.UntilFound);
        await box.SetInert(true);
    }
}
Live sample
ContentEditable
Dir
EnterKeyHint
InputMode
Hidden
Set ContentEditable to True, then click in here and type.
editing modes output
Results will appear here when you interact with the samples.

DOM events

SubscribeEvent

Subscribe to any DOM event on the element with a strongly typed args class per event family - mouse, keyboard, pointer, touch, wheel, focus, input, drag, clipboard and composition. The generic argument must match the event: ButilEvents.Click pairs with ButilMouseEventArgs, ButilEvents.KeyDown with ButilKeyboardEventArgs, and so on. A second overload takes ButilEventListenerOptions for capture, passive and once semantics.

C#
@inject IJSRuntime js

private ButilSubscription? clickSub;

clickSub = await box.SubscribeEvent<ButilMouseEventArgs>(
    js, ButilEvents.Click, args => Console.WriteLine(args.OffsetX));

// capture / passive / once via options:
await input.SubscribeEvent<ButilKeyboardEventArgs>(
    js, ButilEvents.KeyDown, args => Console.WriteLine(args.Key),
    new ButilEventListenerOptions { Once = true });

// element subscriptions must be disposed:
await clickSub.DisposeAsync();
Live sample
Click target - subscribe below, then click me.
Keydown target (the once listener fires a single time)
DOM events output
Results will appear here when you interact with the samples.

Selector matching and removal

Matches / Remove

Matches tests the element against any CSS selector. Remove detaches the element from the DOM - reload the page to bring the demo target back.

Razor
<div @ref="box" data-demo="butil">...</div>

@code {
    private ElementReference box;

    private async Task Check()
    {
        var isMatch = await box.Matches("[data-demo]");

        // Detaches the element from the DOM. Blazor still believes it rendered it, so anything
        // touching the reference afterwards is talking about a node nothing can see.
        await box.Remove();
    }
}
Live sample
Matches is tested against this element, and Remove detaches this one - reload to bring it back.
CSS selector
selector output
Results will appear here when you interact with the samples.

Activation, focus and visibility

Click / Focus / CheckVisibility / Closest

Click sends a synthetic click - the element's own handlers run and default behavior happens, though it does not count as a user gesture. Focus is the overload Blazor's FocusAsync does not give you: preventScroll, for moving focus without yanking the page. CheckVisibility answers what an IntersectionObserver cannot - whether the element is transparent, collapsed, or inside a skipped content-visibility subtree. Closest reports whether the element sits inside anything matching a selector.

Razor
<form>
    <button @ref="button" type="button">Target</button>
    <input @ref="input" />
    <div @ref="box">...</div>
</form>

@code {
    private ElementReference box;
    private ElementReference input;
    private ElementReference button;

    private async Task Activate()
    {
        await button.Click();

        await input.Focus(new FocusOptions { PreventScroll = true });

        var visible = await box.CheckVisibility(new CheckVisibilityOptions
        {
            OpacityProperty = true,
            VisibilityProperty = true,
            ContentVisibilityAuto = true,
        });

        var insideForm = await box.Closest("form");
    }
}
Live sample
Focus target
CheckVisibility and Closest are asked about this element.
Closest selector
activation output
Results will appear here when you interact with the samples.

Classes, data attributes and inline style

AddClass / RemoveClass / ToggleClass / ReplaceClass / ContainsClass / GetClassList / GetData / SetData / RemoveData / GetDataNames / GetStyleText / SetStyleText / GetStyleProperty / SetStyleProperty / RemoveStyleProperty

classList, dataset and style as individual operations rather than as one string you have to parse and rebuild. SetStyleProperty takes CSS property names, custom properties included, so a theme variable can be written from C#. Blazor owns the DOM it rendered and a re-render can undo all of this - use it on elements Blazor renders once, or on ones outside the component.

Razor
<div @ref="box">...</div>

@code {
    private ElementReference box;

    private async Task Style()
    {
        await box.AddClass("card", "highlighted");
        var toggled = await box.ToggleClass("selected");
        var swapped = await box.ReplaceClass("highlighted", "muted");
        var classes = await box.GetClassList();

        await box.SetData("userId", "42");        // writes data-user-id
        var id = await box.GetData("userId");
        var keys = await box.GetDataNames();

        await box.SetStyleProperty("--accent", "#7c3aed");
        await box.SetStyleProperty("outline", "2px solid var(--accent)", important: true);
        var css = await box.GetStyleText();
    }
}
Live sample
Class, data and style target.
Class token
Dataset key
Dataset value
class, data and style output
Results will appear here when you interact with the samples.

Content insertion and serialization

Append / Prepend / Before / After / ReplaceChildren / ReplaceWith / InsertAdjacentText / InsertAdjacentHtml / GetHtml / SetHtml / SetHtmlUnsafe

The DOM insertion methods take elements as well as strings, but only strings can cross the interop boundary - an ElementReference is minted by Blazor's renderer and cannot be handed back from JavaScript. So each string becomes a text node, and InsertAdjacentHtml is how markup gets in. SetHtml runs the browser's sanitizer over what you give it, which is the one to reach for when the markup came from a user; it throws rather than silently falling back where the browser has no sanitizer.

Razor
<div @ref="box">...</div>

@code {
    private ElementReference box;

    private async Task Insert(string untrustedMarkup)
    {
        await box.Append("appended text");
        await box.Prepend("prepended text");
        await box.ReplaceChildren("everything else is gone");

        await box.InsertAdjacentText(InsertPosition.BeforeEnd, "<not markup>");
        await box.InsertAdjacentHtml(InsertPosition.AfterBegin, "<em>trusted markup</em>");

        await box.SetHtml(untrustedMarkup);   // sanitized; throws where unsupported
        var html = await box.GetHtml(new GetHtmlOptions { SerializableShadowRoots = true });
    }
}
Live sample
Original content.
Text or markup to insert
content insertion output
Results will appear here when you interact with the samples.

ARIA and roles

GetAriaLabel / SetAriaLabel / SetAriaExpanded / SetAriaHidden / GetRole / SetRole / AriaNotify

Every aria-* attribute and role, reflected as a property. Prefer writing these as attributes in your markup - it costs no interop and a re-render cannot undo it; reach for these when the value depends on something outside the render tree, or when reading what a component library put on an element. Every value is a string, numeric and boolean ones included, because that is how ARIA itself is defined. AriaNotify announces a message without changing the page; it is Chromium-only and a no-op elsewhere, so keep the visible UI telling the same story.

Razor
<div @ref="box">...</div>

@code {
    private ElementReference box;

    private async Task Describe()
    {
        await box.SetRole("button");
        await box.SetAriaLabel("Close the dialog");
        await box.SetAriaExpanded("true");
        await box.SetAriaHidden("false");

        var label = await box.GetAriaLabel();

        await box.AriaNotify("Upload finished",
            new AriaNotifyOptions { Priority = AriaNotifyPriority.High });
    }
}
Live sample
ARIA target.
aria-label
role
ARIA output
Results will appear here when you interact with the samples.

Popover

GetPopover / SetPopover / ShowPopover / HidePopover / TogglePopover

Turn any element into a popover and drive it from C#. An Auto popover is light-dismissed - Escape or a click outside closes it, and opening one closes the others; a Manual one closes only when the code says so. Show and Hide are no-ops where the browser has no popover support, so a page can call them without feature-detecting first.

Razor
<div @ref="panel">...</div>

@code {
    private ElementReference panel;

    private async Task Popover()
    {
        // The attribute is what makes it a popover; without it the three calls below throw.
        await panel.SetPopover(ElementPopover.Auto);

        await panel.ShowPopover();
        var showing = await panel.TogglePopover();
        await panel.HidePopover();
    }
}
Live sample
I am a popover. Press Escape or click outside to dismiss me.
popover output
Results will appear here when you interact with the samples.

Namespaced attributes, queries and scroll offsets

GetAttributeNS / SetAttributeNS / HasAttributeNS / RemoveAttributeNS / QuerySelectorMatches / QuerySelectorAllCount / GetClientRects / ScrollTo / SetScrollTop / SetScrollLeft

The namespaced attribute methods are what SVG's xlink:href and XML's xml:lang need, and what GetAttribute cannot reach. The query helpers answer the existence and count questions - the elements themselves cannot cross the boundary, so capture the ones you need with @ref. GetClientRects returns one rect per line box, which is more than one for an inline element that wraps. SetScrollTop and SetScrollLeft jump without animating, where ScrollTo can ease.

Razor
<svg><use @ref="icon" /></svg>
<table @ref="table"><tr><td>...</td></tr></table>
<em @ref="inlineText">a long run of text that wraps over several lines</em>
<div @ref="box" style="overflow:auto; max-height:12rem">...</div>

@code {
    private const string Xlink = "http://www.w3.org/1999/xlink";

    private ElementReference box;
    private ElementReference icon;
    private ElementReference table;
    private ElementReference inlineText;

    private async Task Read()
    {
        await icon.SetAttributeNS(Xlink, "xlink:href", "#star");
        var href = await icon.GetAttributeNS(Xlink, "href");

        var hasRows = await table.QuerySelectorMatches("tr");
        var rowCount = await table.QuerySelectorAllCount("tr");

        var rects = await inlineText.GetClientRects();  // one per line box

        await box.SetScrollTop(0);
        await box.ScrollTo(new ScrollOptions { Top = 240, Behavior = ScrollBehavior.Smooth });
    }
}
Live sample

This inline span is long enough to wrap over several line boxes, which is what makes GetClientRects report more than one rectangle for it - one per line the text occupies.

  • first
  • second
  • third
Scroll space.
Descendant selector
namespaced attribute and query output
Results will appear here when you interact with the samples.

Identity, hints and tree facts

Title / Lang / Draggable / Spellcheck / Translate / Autofocus / Autocapitalize / Autocorrect / WritingSuggestions / VirtualKeyboardPolicy / Slot / Part / ElementTiming / LocalName / NamespaceUri / Prefix / ChildElementCount / CurrentCssZoom / AccessKeyLabel / OffsetParentTagName / AssignedSlotName / HasShadowRoot / OuterText

The rest of what an element carries: its tooltip and language, the hints it gives a virtual keyboard and a spell checker, its shadow-DOM wiring, and the facts about where it sits in the tree. Most of these are attributes you can simply render from Blazor at no interop cost - these are for elements that are not yours to re-render, and for reading what something else put there.

Razor
<div @ref="box">...</div>

@code {
    private ElementReference box;

    private async Task Annotate()
    {
        await box.SetTitle("Shown on hover");
        await box.SetLang("fa-IR");
        await box.SetDraggable(true);
        await box.SetSpellcheck(false);
        await box.SetTranslate(false);
        await box.SetAutocapitalize(Autocapitalize.Words);
        await box.SetWritingSuggestions(false);
        await box.SetSlot("content");                      // which shadow slot it asks to land in
        await box.SetPart("surface highlight");            // what ::part() outside the shadow tree can style
        await box.SetElementTiming("hero-image");          // the name Element Timing reports it under

        var localName = await box.GetLocalName();          // "div", where GetTagName gives "DIV"
        var children = await box.GetChildElementCount();
        var zoom = await box.GetCurrentCssZoom();
        var offsetParent = await box.GetOffsetParentTagName();
    }
}
Live sample
Title
Lang
Autocapitalize
Hover for the title, and read the hints and tree facts of this element back.
identity and hints output
Results will appear here when you interact with the samples.

Audio and video

Play / Pause / GetMediaState / SetCurrentTime / SetVolume / SetMuted / SetPlaybackRate

Blazor can render a media element and bind its events, but playback is imperative: there is no markup for 'play now' or 'seek to 30 seconds'. These extensions fill that gap on any ElementReference pointing at an <audio> or <video>. GetMediaState reads the whole transport state in one round trip rather than a property at a time - every read is an interop hop, and polling a dozen of them per frame to draw a scrubber is a dozen messages per frame.

C#
<video @ref="_video" src="clip.webm" playsinline></video>

// starting playback can be refused - autoplay outside a gesture, or an undecodable source:
var started = await _video.Play();

await _video.SetVolume(0.4);       // clamped to 0-1; ignored on iOS, where volume is hardware
await _video.SetMuted(true);       // the mute toggle that works everywhere
await _video.SetPlaybackRate(1.5);
await _video.SetCurrentTime(30);   // false when the media isn't seekable yet

var state = await _video.GetMediaState();
// state.Paused / CurrentTime / Duration / BufferedEnd / ReadyState / VideoWidth ...

await _video.Pause();
Live sample
media output
Results will appear here when you interact with the samples.

Move a node without tearing it down

MoveBefore / IsMoveBeforeSupported

Reparenting with insertBefore disconnects the node first, and everything living inside it goes with it: an iframe reloads, a playing video stops, a running animation restarts, focus is lost. moveBefore does the same move without the disconnection - which is what makes moving a node a reasonable thing to do at all. Pass null as the reference to append at the end.

Razor
<div @ref="column">
    <div @ref="marker">a sibling to insert before</div>
</div>

<div @ref="card">
    <video controls></video>
</div>

@code {
    private ElementReference card;
    private ElementReference column;
    private ElementReference marker;

    private async Task Move()
    {
        // move `card` into `column`, before `marker`
        var moved = await column.MoveBefore(card, marker);

        // or append it at the end
        await column.MoveBefore(card);
    }
}
Live sample
Target column

Blazor owns the DOM it rendered, so a re-render can undo the move - use this for elements Blazor does not re-render.

moveBefore output
Results will appear here when you interact with the samples.
Warning:
Dispose element event subscriptionsSubscribeEvent has no owning service to clean up after you: every subscription holds a .NET object reference and a JS-side handler until its ButilSubscription is disposed. Store the handle and dispose it in DisposeAsync, exactly as this page does.

API reference (extension methods on ElementReference)

Member
Signature
Description
GetAttribute
ValueTask<string> GetAttribute(string name)
Returns the value of the named attribute.
SetAttribute
ValueTask SetAttribute(string name, string value)
Sets the named attribute. Values are written verbatim - validate untrusted input.
GetAttributeNames
ValueTask<string[]> GetAttributeNames()
Returns the names of all attributes present on the element.
HasAttribute
ValueTask<bool> HasAttribute(string name)
Whether the named attribute is present.
HasAttributes
ValueTask<bool> HasAttributes()
Whether the element has any attributes at all.
ToggleAttribute
ValueTask<bool> ToggleAttribute(string name, bool? force)
Toggles a boolean attribute; force pins it on (true) or off (false). Returns the resulting presence.
RemoveAttribute
ValueTask RemoveAttribute(string name)
Removes the named attribute.
GetBoundingClientRect
ValueTask<Rect> GetBoundingClientRect()
Size and viewport-relative position of the element.
Scroll
ValueTask Scroll(ScrollOptions? options)
Scrolls the element to absolute coordinates with optional smooth behavior.
Scroll
ValueTask Scroll(double? x, double? y)
Scrolls the element to the given coordinates.
ScrollBy
ValueTask ScrollBy(ScrollOptions? options)
Scrolls the element by a relative amount with optional smooth behavior.
ScrollBy
ValueTask ScrollBy(double? x, double? y)
Scrolls the element by the given relative amount.
ScrollIntoView
ValueTask ScrollIntoView()
Scrolls the page until the element is visible.
ScrollIntoView
ValueTask ScrollIntoView(bool alignToTop)
Scrolls the element into view, aligned to the top or bottom of the scrollport.
ScrollIntoView
ValueTask ScrollIntoView(ScrollIntoViewOptions options)
Scrolls the element into view with behavior, block and inline positioning.
Blur
ValueTask Blur()
Removes keyboard focus from the element.
SetPointerCapture
ValueTask SetPointerCapture(int pointerId)
Routes future events of the given pointer to this element.
HasPointerCapture
ValueTask<bool> HasPointerCapture(int pointerId)
Whether this element currently captures the given pointer.
ReleasePointerCapture
ValueTask ReleasePointerCapture(int pointerId)
Releases a previously set pointer capture.
RequestPointerLock
ValueTask RequestPointerLock()
Asynchronously asks for the pointer to be locked on the element.
RequestFullScreen
ValueTask RequestFullScreen(FullScreenOptions? options)
Asks the browser to present the element fullscreen. The options parameter is required (pass null for defaults).
Matches
ValueTask<bool> Matches(string selectors)
Whether the element would be selected by the given CSS selector.
Remove
ValueTask Remove()
Removes the element from its parent in the DOM.
GetId / SetId
ValueTask<string> GetId() · ValueTask SetId(string id)
The element's id.
GetClassName / SetClassName
ValueTask<string> GetClassName() · ValueTask SetClassName(string className)
The element's class attribute as a single string.
GetInnerHtml / SetInnerHtml
ValueTask<string> GetInnerHtml() · ValueTask SetInnerHtml(string innerHtml)
The element's content markup. The setter bypasses Blazor encoding - trusted input only.
GetOuterHtml / SetOuterHtml
ValueTask<string> GetOuterHtml() · ValueTask SetOuterHtml(string outerHtml)
The element's markup including itself. The setter replaces the element - trusted input only.
GetInnerText / SetInnerText
ValueTask<string> GetInnerText() · ValueTask SetInnerText(string value)
The rendered text content of the element and its descendants.
GetAccessKey / SetAccessKey
ValueTask<string> GetAccessKey() · ValueTask SetAccessKey(string key)
The keyboard access key assigned to the element.
GetTabIndex / SetTabIndex
ValueTask<int> GetTabIndex() · ValueTask SetTabIndex(int value)
The element's position in the tabbing order.
GetClientHeight
ValueTask<float> GetClientHeight()
Inner height (padding box) in px.
GetClientWidth
ValueTask<float> GetClientWidth()
Inner width (padding box) in px.
GetClientTop
ValueTask<float> GetClientTop()
Top border width in px.
GetClientLeft
ValueTask<float> GetClientLeft()
Left border width in px.
GetOffsetHeight
ValueTask<float> GetOffsetHeight()
Height including padding and borders in px.
GetOffsetWidth
ValueTask<float> GetOffsetWidth()
Layout width including padding and borders in px.
GetOffsetTop
ValueTask<float> GetOffsetTop()
Distance to the top of the offset parent in px.
GetOffsetLeft
ValueTask<float> GetOffsetLeft()
Distance to the left of the offset parent in px.
GetScrollHeight
ValueTask<float> GetScrollHeight()
Total scrollable height in px.
GetScrollWidth
ValueTask<float> GetScrollWidth()
Total scrollable width in px.
GetScrollTop
ValueTask<float> GetScrollTop()
Current vertical scroll offset in px.
GetScrollLeft
ValueTask<float> GetScrollLeft()
Current horizontal scroll offset in px.
GetTagName
ValueTask<string> GetTagName()
The element's tag name (uppercase for HTML elements).
GetContentEditable / SetContentEditable
ValueTask<ContentEditable> GetContentEditable() · ValueTask SetContentEditable(ContentEditable value)
Whether the element is editable: Inherit, True, False or PlainTextOnly.
IsContentEditable
ValueTask<bool> IsContentEditable()
The effective (inherited) editability of the element.
GetDir / SetDir
ValueTask<ElementDir> GetDir() · ValueTask SetDir(ElementDir value)
Text writing directionality: NotSet, Ltr, Rtl or Auto.
GetEnterKeyHint / SetEnterKeyHint
ValueTask<EnterKeyHint> GetEnterKeyHint() · ValueTask SetEnterKeyHint(EnterKeyHint value)
The action label the virtual keyboard shows for the Enter key.
GetInputMode / SetInputMode
ValueTask<InputMode> GetInputMode() · ValueTask SetInputMode(InputMode value)
The virtual keyboard type hint (numeric, email, tel, ...).
GetHidden / SetHidden
ValueTask<Hidden> GetHidden() · ValueTask SetHidden(Hidden value)
The hidden attribute: False, True or UntilFound.
GetInert / SetInert
ValueTask<bool> GetInert() · ValueTask SetInert(bool value)
When true, the browser ignores all user input events for the element.
SubscribeEvent<T>
Task<ButilSubscription> SubscribeEvent<T>(IJSRuntime js, string domEvent, Action<T> listener, bool useCapture = false, bool preventDefault = false, bool stopPropagation = false)
Subscribes a typed listener to a DOM event on the element. Dispose the returned handle to detach.
SubscribeEvent<T>
Task<ButilSubscription> SubscribeEvent<T>(IJSRuntime js, string domEvent, Action<T> listener, ButilEventListenerOptions options, bool preventDefault = false, bool stopPropagation = false)
Overload with addEventListener options: Capture, Passive, Once - and MinInterval, which rate-limits the handler in JavaScript before the round trip. Reach for it on a pointermove listener over a canvas, where every event is otherwise a round trip.
ButilEventListenerOptions.MinInterval
TimeSpan? MinInterval { get; set; }
Shortest time between two calls into the handler. Null or Zero (the default) forwards every event. Leading-edge with a trailing send, so the last event of a gesture always arrives.
Play
ValueTask<bool> Play()
Starts playback on an audio/video element. False when the browser refused - autoplay blocked outside a gesture, or an undecodable source.
Pause
ValueTask Pause()
Pauses playback. No-op when already paused.
Load
ValueTask Load()
Resets the element and reloads its source - what you call after changing src by hand.
GetMediaState
ValueTask<MediaElementState?> GetMediaState()
The whole playback state in one round trip: paused, ended, seeking, muted, loop, volume, rate, currentTime, duration, readyState, bufferedEnd, video size. Null when the reference isn't a media element.
SetCurrentTime
ValueTask<bool> SetCurrentTime(double seconds)
Seeks. False when the media isn't seekable yet - typically because its metadata hasn't loaded.
SetVolume
ValueTask SetVolume(double volume)
0 to 1, clamped rather than rejected. Ignored on iOS, where volume is a hardware control.
SetMuted
ValueTask SetMuted(bool muted)
Mutes or unmutes without changing the volume - the mute toggle that works everywhere.
SetLoop
ValueTask SetLoop(bool loop)
Turns looping on or off.
SetPlaybackRate
ValueTask<bool> SetPlaybackRate(double rate)
1 is normal speed. False when the engine rejected the rate as outside what it can resample.
SetMediaSource
ValueTask SetMediaSource(string src)
Points the element at a new URL - including a blob: one from ObjectUrls or a finished recording. Follow with Load.
CanPlayType
ValueTask<string> CanPlayType(string mimeType)
The browser's own three-valued answer: "probably", "maybe", or "" for no. Deliberately not a bool.
Click
ValueTask Click()
Sends a synthetic click: handlers run, the event bubbles and default behavior happens. Not a user gesture, so gesture-gated APIs still refuse.
Focus
ValueTask Focus(FocusOptions? options = null)
Focuses the element. PreventScroll keeps the page where it is; FocusVisible overrides the focus-ring heuristic (Firefox).
CheckVisibility
ValueTask<bool> CheckVisibility(CheckVisibilityOptions? options = null)
Whether the element is rendered - and optionally whether opacity, visibility and skipped content-visibility subtrees count against it.
Closest
ValueTask<bool> Closest(string selectors)
Whether the element or any ancestor matches the selector. The DOM method hands back the matching ancestor, which cannot cross the boundary - so this answers whether one was found.
ScrollTo
ValueTask ScrollTo(ScrollOptions? options) · ValueTask ScrollTo(double? x, double? y)
The same operation as Scroll, under the DOM's other name for it.
SetScrollTop / SetScrollLeft
ValueTask SetScrollTop(double value) · ValueTask SetScrollLeft(double value)
Jumps the element's scroll offset, clamped by the browser to the scrollable range.
GetScrollTopMax / GetScrollLeftMax
ValueTask&lt;float&gt; GetScrollTopMax() · ValueTask&lt;float&gt; GetScrollLeftMax()
The largest offset the setters will take. A Firefox property; computed from scroll and client sizes elsewhere.
GetAttributeNS / SetAttributeNS
ValueTask&lt;string&gt; GetAttributeNS(string namespaceUri, string localName) · ValueTask SetAttributeNS(string namespaceUri, string qualifiedName, string value)
Namespaced attributes - xlink:href, xml:lang - which GetAttribute cannot reach.
HasAttributeNS / RemoveAttributeNS
ValueTask&lt;bool&gt; HasAttributeNS(string namespaceUri, string localName) · ValueTask RemoveAttributeNS(string namespaceUri, string localName)
Presence and removal for a namespaced attribute.
GetClientRects
ValueTask<Rect[]> GetClientRects()
Every border box the element occupies - more than one for an inline element that wraps across lines. Empty for display:none.
After / Before / Append / Prepend
ValueTask Append(params string[] nodes)
Inserts text nodes around or inside the element. Strings only - an ElementReference cannot be handed back from JavaScript.
ReplaceChildren / ReplaceWith
ValueTask ReplaceChildren(params string[] nodes) · ValueTask ReplaceWith(params string[] nodes)
Replaces the element's children, or the element itself. Passing nothing to ReplaceChildren empties it.
InsertAdjacentHtml
ValueTask InsertAdjacentHtml(InsertPosition position, string html)
Parses markup and inserts it without reparsing existing children. Bypasses Blazor encoding - trusted input only.
IsMoveBeforeSupported
ValueTask<bool> IsMoveBeforeSupported()
True when the runtime implements Element.moveBefore().
MoveBefore
ValueTask<bool> MoveBefore(ElementReference node, ElementReference? reference = null)
Moves a node into this element, before the reference (or at the end when null), without disconnecting it - iframes keep loading, animations keep running, focus is preserved.
InsertAdjacentText
ValueTask InsertAdjacentText(InsertPosition position, string text)
Inserts a text node at the given position. Markup in the string stays text.
GetHtml
ValueTask<string> GetHtml(GetHtmlOptions? options = null)
Serializes the contents, optionally including serializable shadow roots - which InnerHtml always leaves out.
SetHtml
ValueTask SetHtml(string html)
Replaces the contents, sanitized by the browser. Throws where unsupported rather than falling back to a write that skips the sanitizer.
SetHtmlUnsafe
ValueTask SetHtmlUnsafe(string html)
Replaces the contents without sanitizing, parsing declarative shadow roots. Trusted markup only.
AddClass / RemoveClass
ValueTask AddClass(params string[] tokens) · ValueTask RemoveClass(params string[] tokens)
classList.add and .remove; tokens already present or already absent are ignored.
ToggleClass
ValueTask<bool> ToggleClass(string token, bool? force = null)
Flips a class, or pins it with force. Returns whether it is on the element afterwards.
ReplaceClass
ValueTask<bool> ReplaceClass(string oldToken, string newToken)
Swaps one class for another in place. False - and no change - when the old one was not there.
ContainsClass / GetClassList
ValueTask&lt;bool&gt; ContainsClass(string token) · ValueTask&lt;string[]&gt; GetClassList()
Membership test, and the classes as tokens rather than as one string.
GetData / SetData / RemoveData
ValueTask&lt;string?&gt; GetData(string key) · ValueTask SetData(string key, string value) · ValueTask RemoveData(string key)
One data-* attribute by its dataset key - userId for data-user-id. Null when the attribute is absent.
GetDataNames
ValueTask<string[]> GetDataNames()
The dataset keys the element carries, not the attribute names.
GetStyleText / SetStyleText
ValueTask&lt;string&gt; GetStyleText() · ValueTask SetStyleText(string value)
The whole inline style, as it would be written in a style attribute. Inline only - not what a stylesheet contributes.
GetStyleProperty / SetStyleProperty
ValueTask&lt;string&gt; GetStyleProperty(string name) · ValueTask SetStyleProperty(string name, string value, bool important = false)
One inline declaration by CSS property name, custom properties (--accent) included.
RemoveStyleProperty
ValueTask<string> RemoveStyleProperty(string name)
Removes one inline declaration and returns what it held.
ShowPopover / HidePopover
ValueTask ShowPopover() · ValueTask HidePopover()
Shows or hides the element as a popover in the top layer. No-ops where the browser has no popover support.
TogglePopover
ValueTask<bool> TogglePopover(bool? force = null)
Flips the popover, or pins it with force. Returns whether it is showing afterwards.
GetPopover / SetPopover
ValueTask&lt;ElementPopover&gt; GetPopover() · ValueTask SetPopover(ElementPopover value)
What kind of popover the element is: NotSet, Auto, Manual or Hint.
QuerySelectorMatches
ValueTask<bool> QuerySelectorMatches(string selectors)
Whether any descendant matches. The element itself cannot cross the boundary - capture what you need with @ref.
QuerySelectorAllCount
ValueTask<int> QuerySelectorAllCount(string selectors)
How many descendants match.
GetAria* / SetAria*
ValueTask&lt;string&gt; GetAriaLabel() · ValueTask SetAriaLabel(string value)
Every aria-* attribute as a property pair - Atomic, AutoComplete, Busy, Checked, Current, Description, Disabled, Expanded, HasPopup, Hidden, Invalid, KeyShortcuts, Label, Level, Live, Modal, Multiline, MultiSelectable, Orientation, Placeholder, Pressed, ReadOnly, Relevant, Required, RoleDescription, Selected, Sort, Value*, the grid Col*/Row*/PosInSet/SetSize family and the braille pair. All strings, numeric and boolean ones included.
GetRole / SetRole
ValueTask&lt;string&gt; GetRole() · ValueTask SetRole(string value)
The element's ARIA role, for when the tag alone does not say what it is.
AriaNotify
ValueTask AriaNotify(string message, AriaNotifyOptions? options = null)
Announces a message to assistive technology without changing the page. Experimental and Chromium-only; a no-op elsewhere.
GetTitle / SetTitle
ValueTask&lt;string&gt; GetTitle() · ValueTask SetTitle(string value)
The advisory text a browser shows as a tooltip.
GetLang / SetLang
ValueTask&lt;string&gt; GetLang() · ValueTask SetLang(string value)
The element's language as a BCP 47 tag.
GetDraggable / SetDraggable
ValueTask&lt;bool&gt; GetDraggable() · ValueTask SetDraggable(bool value)
Whether the element can be dragged.
GetSpellcheck / SetSpellcheck
ValueTask&lt;bool&gt; GetSpellcheck() · ValueTask SetSpellcheck(bool value)
Whether the browser spell-checks what the user types.
GetTranslate / SetTranslate
ValueTask&lt;bool&gt; GetTranslate() · ValueTask SetTranslate(bool value)
Whether the text should be translated when the page is. False for code and identifiers.
GetAutofocus / SetAutofocus
ValueTask&lt;bool&gt; GetAutofocus() · ValueTask SetAutofocus(bool value)
Whether the element asks for focus on load. Setting it afterwards does nothing on its own - use Focus.
GetAutocapitalize / SetAutocapitalize
ValueTask&lt;Autocapitalize&gt; GetAutocapitalize() · ValueTask SetAutocapitalize(Autocapitalize value)
How a virtual keyboard capitalizes typed text: None, Off, On, Sentences, Words or Characters.
GetAutocorrect / SetAutocorrect
ValueTask&lt;bool&gt; GetAutocorrect() · ValueTask SetAutocorrect(bool value)
Whether the browser may autocorrect typed text. Safari and Chromium.
GetWritingSuggestions / SetWritingSuggestions
ValueTask&lt;bool&gt; GetWritingSuggestions() · ValueTask SetWritingSuggestions(bool value)
Whether inline writing suggestions are offered. The DOM property is the string true or false; this is the boolean it stands for.
GetVirtualKeyboardPolicy / SetVirtualKeyboardPolicy
ValueTask&lt;VirtualKeyboardPolicy&gt; GetVirtualKeyboardPolicy() · ValueTask SetVirtualKeyboardPolicy(VirtualKeyboardPolicy value)
Who shows the on-screen keyboard for a contenteditable element: Auto or Manual. Chromium only.
GetSlot / SetSlot
ValueTask&lt;string&gt; GetSlot() · ValueTask SetSlot(string value)
The shadow-DOM slot the element asks to be placed in.
GetAssignedSlotName
ValueTask<string> GetAssignedSlotName()
The slot it actually landed in, by name. Null when it is not slotted.
GetPart / SetPart
ValueTask&lt;string[]&gt; GetPart() · ValueTask SetPart(string value)
The shadow parts the element exposes to ::part() selectors.
HasShadowRoot
ValueTask<bool> HasShadowRoot()
Whether the element hosts an open shadow root. False for a closed one, which is the point of closing it.
GetElementTiming / SetElementTiming
ValueTask&lt;string&gt; GetElementTiming() · ValueTask SetElementTiming(string value)
Marks the element for Element Timing under a name. Only works before it is first painted.
GetLocalName
ValueTask<string> GetLocalName()
The tag name without a prefix, in the document's case - lowercase in HTML, where GetTagName reports uppercase.
GetNamespaceUri / GetPrefix
ValueTask&lt;string&gt; GetNamespaceUri() · ValueTask&lt;string&gt; GetPrefix()
The namespace the element belongs to, and its prefix within it.
GetChildElementCount
ValueTask<int> GetChildElementCount()
How many element children it has - text nodes and comments not counted.
GetCurrentCssZoom
ValueTask<double> GetCurrentCssZoom()
The effective CSS zoom on the element - the factor between reported geometry and the layout's own units. 1 when nothing is zoomed.
GetAccessKeyLabel
ValueTask<string> GetAccessKeyLabel()
How the element's access key would be shown to the user - Alt+S, or ⌃⌥S on a Mac. Empty where the engine computes none.
GetOffsetParentTagName
ValueTask<string> GetOffsetParentTagName()
The tag name of the nearest positioned ancestor - what the offset metrics are measured against.
GetOuterText / SetOuterText
ValueTask&lt;string&gt; GetOuterText() · ValueTask SetOuterText(string value)
Reads the rendered text; writing replaces the element itself, leaving the reference dangling. The DOM's own asymmetry.
GetNonce / SetNonce
ValueTask&lt;string&gt; GetNonce() · ValueTask SetNonce(string value)
The element's CSP nonce. Browsers hide the attribute from scripts; the property is what remains.
An unhandled error has occurred. Reload 🗙