WLJS LogoWLJS Notebook

WLX

Type .wlx in the first line of an input cell and start writing WLX on a new line:

.wlx <Now/>
Fri 2 Jan 2026 16:11:04

Make sure the first letter in a symbol name is capitalized. This is required by WLX syntax.

This allows you to use Wolfram Language XML extension in your cell. It's extremely powerful and especially useful when creating complex cell structures, components for presentations, mini-apps, or enhancing output with the power of HTML, CSS, and JavaScript.

You can think of WLX as WL and plain HTML extended to work with each other. It allows you to write Wolfram Language using XML tags and build HTML templates using Wolfram Expressions.

Unlike JSX, you can write a plain HTML inside WLX scripts with no restrictions.

Tags

Wolfram expressions always start with a capital letter, while plain HTML tags must remain in a lower case:

.wlx <div></div>
.wlx <Div></Div>

Ownvalues and Downvalues

OwnValue of a symbol corresponds to self-closing tags with no attributes, while DownValue of a symbol corresponds to normal tags with or without attributes. For example:

TimeNow := TextString[Now];
StringReverse[TimeNow]

can be written as

.wlx TimeNow := TextString[Now]; <StringReverse> <TimeNow/> </StringReverse>

First child element is the first argument of a given function and etc.

Any symbol defined within WLX cell is in `Global`` context

Output form

Any symbol in Wolfram Language has a few predefined output forms. StandardForm is shown in all output cells, while WLXForm is shown in WLX, slide, markdown output cells and is usually some sort of a string.

If WLXForm is not defined for a given symbol, ToString is applied

For example:

SpecialSymbol; SpecialSymbol /: MakeBoxes[SpecialSymbol, WLXForm] := MakeBoxes["Hey!", WLXForm]

then if you evaluate SpecialSymbol in WLX cell, it will print "Hey!" to a DOM tree:

.wlx <SpecialSymbol/>

Many symbols have predefined WLXForm, namely: Graphics, Graphics3D, Image, EventObject, any GUI input elements and many more.

However, a basic plot will work out of the box:

MyPlot = Plot[x, {x,0,1}];
.wlx <MyPlot/>

Passing arguments

  1. Any argument passed to an expression is converted to a string (or specifically WLXForm)

  2. Plain text content counts as an argument too

  3. Tags attributes are passed as options

Here is a function, that takes 3 arguments, but prints only the 2nd one:

.wlx SomeFunction[Arg1_, Arg2_, Arg3_] := <h3><Arg2/></h3> <SomeFunction> <div>You will not see me</div> You will see only me <Now/> </SomeFunction>

Attributes interpolation

This is a crucial thing, when it comes to a markup. Curly braces with double quotes can be used to interpolate strings in HTML attributes:

.wlx With[{ url = "upload.wikimedia.org/wikipedia/commons/7/70/Oftheunicorn.jpg" }, <img width="300" src="https://{url}"/> ]

Any Wolfram expressions are allowed inside the braces

.wlx With[{ url = {"upload.wikimedia.org/wikipedia/commons/7/70/Oftheunicorn.jpg"} }, <img width="300" src="https://{url[[1]]}"/> ]

Attributes of symbols

If you pass an HTML attribute to a Wolfram symbol, it will be translated to an option, i.e.

.wlx <Heading title={"Some title"}/>

where we defined Heading as

.wlx Heading[OptionsPattern[]] := With[{Title = OptionValue["title"]}, <h1>This is some <Title/></h1> ] Options[Heading] = {"title" -> "Empty title"}

The same can be done for tags with children:

.wlx <TagName option1={1+1} option2={Now}> whatever </TagName>

where all passed arguments go firstly and before the OptionsPattern[]:

.wlx TagName[child_, OptionsPattern[]] := ... TagName[children__, OptionsPattern[]] := ...

Escaping

Use special <Escape> tag to avoid interpretation of tags inside:

.wlx <Escape> <Div>It won't be parsed by WLX</Div> </Escape>

The inner content will not be parsed and, but will be returned as string

Iterators, branching?

HTML/XML is a markup language by its nature. Therefore we recommend to use Wolfram Language making tables, conditional rendering for that:

.wlx Columns[YourList__] := Table[ <div class="lg:pr-4"> <div class="text-base leading-7 text-gray-700 "> <Child/> </div> </div> , {Child, List[YourList]}]; <div class="flex flex-col"> <Columns> <p>This is column 1</p> <p>This is column 2</p> <p>This is column 3</p> </Columns> </div>

Here a multiple <p> tags are substituted as a sequence of arguments to Columns function, that iterates over them and forms a wrapper HTML structure. Then the result is substituted into the bottom div col structure.

Here is another way to build lists from raw data:

.wlx With[{ TableList = Table[ With[{SomeField = item["Field"]}, <li class="red"><SomeField/></li> ] , {item, YouList}] }, <ul> <TableList/> </ul> ]
Putting a plain text separated by multiple linebreaks counts as a single argument. Wrap each line with <span> or <p> or <Identity> if you want them to be separable

A few things to keep in mind

There are certain rules you should sticked to in order to avoid headaches

Keep only one or zero root element

This implies that this one will be exported to the output, like in CompoundExpression.

Always close any XML tags

Modern web-browsers are quite forgiving, when it comes to the syntax mistakes. WLX parser decodes the whole tree of HTML and WL and, then, builds an AST. Therefore, always close tags explicitly

.wlx <img src="http://..."/>

More examples

Embed Figures into a Custom Layout

Plot a function and assign it to a symbol:

Figure = Plot[Sinc[5x], {x, -5, 5}]

Then, in a new cell, type:

.wlx <div> <style> @keyframes tilt-shaking { 0% { transform: rotate(0deg); } 25% { transform: rotate(5deg); } 50% { transform: rotate(0deg); } 75% { transform: rotate(-5deg); } 100% { transform: rotate(0deg); } } </style> <div style="animation: tilt-shaking 0.35s infinite"> <Figure/> </div> </div>

Now your plot will shake infinitely 😉

Creating Components

Let's define a hybrid WL function:

Heading[Text_, OptionPattern[]] := With[{color = OptionValue["Color"]}, <h2 style="color: {color}"><Text/></h2>; ] Options[Heading] = {"Color" -> "black"};

You can now use it in your layout:

.wlx <Heading Color={"blue"}> Hello World! </Heading>

this will work on slides and markdown cells as well:

.slide # Slide title <Heading Color={"red"}> Hello World! </Heading>

Two-Column Layout Using Flexbox

You can fine-tune the layout since you're working directly with HTML and CSS. For example, here's a slider and a plot aligned in a row:

.wlx Module[{Slider = InputRange[0.1, 1, 0.1, 0.5], Figure, lines}, EventHandler[Slider, Function[data, lines = {#, Sinc[#/data]} & /@ Range[-5, 5, 0.1]]]; Slider // EventFire; Figure = Graphics[Line[lines // Offload], ImageSize -> 350]; <div style="display: flex"> <div><Slider/></div> <div><Figure/></div> </div> ]

On this page