Public
Edited
Dec 4, 2023
Paused
1 star
Insert cell
Insert cell
What's up <x-mark orange>doc</x-mark>? This is a test <x-mark>boodle</x-mark> <x-mark class="green">boodle doodle this is a longer one</x-mark> and then some more text. <x-mark>Boodle boodle doodle this is an even longer one</x-mark> and then some <x-mark pink>more text</x-mark>. <x-mark blue>Boodle boodle longer one</x-mark> and then some more text. <x-mark>Boodle boodle doodle this is a much longer one this is a much longer one this is a much longer one this is a much longer one this is a much longer one</x-mark> and then some more text. Then some more text. Then some more text. Then some more text. Then some more text. Then some more text. Then some more text. <x-mark pink>Boodle doodle doodle</x-mark>.
Insert cell
Insert cell
<style>
x-mark[blue] {
--color: rgb(0,200,255);
}
x-mark[orange] {
--color: rgb(255,170,0);
}
x-mark.green {
--color: rgb(0,255,0);
}
x-mark[pink] {
--color: rgb(255,0,170);
}
</style>
Insert cell
makeCustomHighlighterTag("x-mark")
Insert cell
function makeCustomHighlighterTag(
tagName = "x-mark",
defaultColor = "rgb(255,255,0)"
) {
class HighlighterStyleElement extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: "open" });
let hPadding = 0.25;
let vPadding = 0.15;
let hOffset = (2 * Math.random() - 1) * hPadding;
let vOffset = (2 * Math.random() - 1) * vPadding;
let minAngle = Math.max(90 - this.textContent.length / 1.5, 20);
let maxAngle = Math.min(minAngle + 20, 90);
let angle = minAngle + (maxAngle - minAngle) * Math.random();
let top = vPadding + vOffset;
let bottom = vPadding - vOffset;
let left = hPadding - hOffset;
let right = hPadding + hOffset;
this.shadowRoot.innerHTML = `
<style>
:host {
--color: ${defaultColor};
}
mark {
margin: ${-top}em ${-right}em ${-bottom}em ${-left}em;
padding: ${top}em ${right}em ${bottom}em ${left}em;
border-radius: 0.5em 0.3em;
background: transparent;
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
background-image: linear-gradient(
${angle}deg,
color-mix(in srgb, var(--color), transparent 50%),
color-mix(in srgb, var(--color), transparent 90%) 4%,
color-mix(in srgb, var(--color), transparent 70%) 96%,
color-mix(in srgb, var(--color), transparent 30%)
);
}
</style>
<mark>${this.textContent}</mark>
`;
}
}

customElements.get(tagName) ||
customElements.define(tagName, HighlighterStyleElement);

return html`<span style="color:grey;"><span style="font:var(--monospace-font);">&lt;${tagName}&gt;</span> is defined for highlighter-type styles. Use <span style="font:var(--monospace-font);">${tagName} {--color: ...};</span> to style.</span>`;
}
Insert cell
I think I might like having a custom tag (<x-mark pink>like this</x-mark>) rather than a function ${marked("like this", "pink")} but it's pretty similar. The component has the downside that I don't think there's any way to "de-register" the name, so once it's defined it takes a hard refresh to change it.
Insert cell
<style>
mark.pink {
--color: rgb(255,0,170);
}
</style>
Insert cell
function marked(text, cls = "", defaultColor = "rgb(255,255,0)") {
return html`<mark class="${cls}" --color: ${defaultColor}; style="${makeStyle(
text
)}">${text}</mark>`;
}
Insert cell
function makeStyle(text) {
let hPadding = 0.25;
let vPadding = 0.15;
let hOffset = (2 * Math.random() - 1) * hPadding;
let vOffset = (2 * Math.random() - 1) * vPadding;
let minAngle = Math.max(90 - text.length / 1.5, 20);
let maxAngle = Math.min(minAngle + 20, 90);
let angle = minAngle + (maxAngle - minAngle) * Math.random();
let top = vPadding + vOffset;
let bottom = vPadding - vOffset;
let left = hPadding - hOffset;
let right = hPadding + hOffset;
let raw = `margin: ${-top}em ${-right}em ${-bottom}em ${-left}em;
padding: ${top}em ${right}em ${bottom}em ${left}em;
border-radius: 0.5em 0.3em;
background: transparent;
box-decoration-break: clone;
-webkit-box-decoration-break: clone;
background-image: linear-gradient(
${angle}deg,
color-mix(in srgb, var(--color), transparent 50%),
color-mix(in srgb, var(--color), transparent 90%) 4%,
color-mix(in srgb, var(--color), transparent 70%) 96%,
color-mix(in srgb, var(--color), transparent 30%)
);`;
return raw.split(/\s+/).join(" ");
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more