Replies: 2 comments 1 reply
-
|
Hi Tyler,
Thank you for your support and feedback; it is incredibly helpful for the
entire team and especially for Daniel. This request might be moved to the
"Future Requests" section, but I want to officially second your proposal
for stable CSS class names on SVG elements.
Adding classes like at-role-mainGlyph, at-role-staffLine, and
at-role-barNumber would significantly simplify troubleshooting via browser
inspector tools. Furthermore, having specific class names for elements like
the Tuner Display, Staff Rows, Cursor, Loop, and Lyrics would be highly
beneficial for long-term maintenance and filtering within individual
repositories.
Regarding the related discussions you mentioned:
- Dark and light modes are currently available and used by several
community members.
- For advanced notation and element coloring, I recommend looking at the
"ItsMyTabs" project from the LouisLam repository. He has implemented an
"all-in-one" setup in Tab.vue and uses Rocksmith color schemes within
Settings.vue. There are certainly many options available with alphaTab.
Best regards,
Brett Bolzenthal
…On Wed, Jul 1, 2026 at 7:34 AM Tyler Peckenpaugh ***@***.***> wrote:
First off — thank you for alphaTab. It's an impressively complete piece of
engineering, and the SVG rendering path in particular has made things
possible for me that I wouldn't have attempted otherwise. This is a
"wouldn't it be nice" idea, not a complaint — happy for it to just sit here
as a discussion, and totally understand if it's not a priority or not the
direction you want to take things.
The idea
Right now, every SVG element alphaTab renders gets its fill/stroke from
one named display.resources role (mainGlyphColor, secondaryGlyphColor,
staffLineColor, barSeparatorColor, barNumberColor, scoreInfoColor). I'd
love a way to select "all elements colored via role X" directly from CSS —
right now the only handle available is the literal color value itself.
The workaround I've found: since there's no CSS hook for "this role" other
than the literal fill/stroke value alphaTab assigns, one option is to
write a CSS attribute selector that matches on that value directly — e.g.
[fill="#ffe600"] if that's the real mainGlyphColor. A further refinement
is to assign each role a placeholder RGB value with no relation to the real
desired color, used purely as a stable matching key, and let a separate
stylesheet substitute in the actual color afterward — that at least avoids
re-touching CSS every time the real color changes. But either way, the same
fragility applies: if two roles ever resolve to the same fill value,
elements from both roles get picked up by the same CSS rule with no error
or warning, silently merging their styling. And using a color as the thing
you match against in order to *change that same color* feels inherently
unintuitive — the selector doesn't encode any meaning about what the
element actually is, just what it happens to look like right now.
So the ask: it'd be great if alphaTab emitted a stable, documented CSS
class on every SVG element indicating which display.resources role
produced its color — something like class="at-role-mainGlyph",
at-role-staffLine, at-role-barNumber. This wouldn't require any further
semantic sub-splitting of a role — it'd just be a way to target the
existing six roles from CSS directly, instead of matching on color values.
What I found poking around the source (might be useful, might be missing
context)
All SVG emission seems to funnel through one place: SvgCanvas (
packages/alphatab/src/platform/svg/SvgCanvas.ts), with CssFontSvgCanvas
handling music-symbol glyphs. There's actually already precedent for this
kind of thing — CssFontSvgCanvas already wraps every music-symbol glyph
in class="at" unconditionally.
Colors get assigned to canvas.color from a lot of call sites — I counted
roughly 60+, across ~15 files, including ElementStyleHelper/
ElementStyleScope plus several renderer/glyph classes that set it
directly. My first instinct was that this would mean a fairly invasive
change. But it looks like RenderingResources constructs each of the six
default colors as its own distinct object, and every call site assigns by
reference rather than copying the value — so it seems like the canvas layer
could determine the active role via reference-equality checks against the
six known RenderingResources fields, right at the point of emission,
without touching any of those ~15 files. Per-element style overrides (the
existing NoteSubElement/BeatSubElement .style mechanism) produce distinct
Color objects, so they'd naturally fall through without a role class —
which seems like the right behavior rather than a gap, though I'd defer to
you on that.
One likely blocker worth being upfront about: alphaTab actually has three
render engines — svg (CssFontSvgCanvas), skia (SkiaCanvas), and html5 (
Html5Canvas, browser Canvas 2D). The skia and html5 engines both draw to
a raster canvas with no per-element output at all — there's nothing a
class attribute could attach to in that model. So this proposal is
inherently SVG-only, not something that could be extended to the other
backends later — it's a structural property of canvas rendering, not a
missing feature there. If keeping capability parity across render engines
is a design goal for alphaTab, that alone might be a reason to decline
this, and I'd understand if so — just wanted to flag it rather than have it
come up as a surprise.
One other thing I couldn't verify: given the transpiler package in the
repo, I'm guessing the C#/Kotlin SVG output is generated from this
TypeScript source rather than hand-maintained separately, so this would
hopefully propagate for free — but I could easily be wrong about that.
If I'm reading it right, this looks like it could be a fairly small,
low-risk, mostly-one-file change, with a pattern that already exists
elsewhere in the codebase — but you'd obviously know far better than I
would whether that's actually true once you get into it.
Related discussion
I came across #1048
<#1048> ("Dark mode
score rendering") and #1558
<#1558> ("Is it possible
to customize appearance?") while searching — #1048
<#1048> is about
switching whole color presets, and #1558
<#1558> is about API
ergonomics for constructing Color/Font instances. Neither seemed to cover
this specifically, but flagging them in case I've missed the connection.
If this is something you'd want on the roadmap, I'd be happy to put
together a pull request for it myself — just let me know and I'll get
started.
Thanks for reading this far, and for everything you've built here either
way!
—
Reply to this email directly, view it on GitHub
<#2758?email_source=notifications&email_token=BNLESQEJHBRNUBZHP2QDJRD5CUOOZA5CNFSNUABBM5UWIORPF5TWS5BNNB2WEL2ENFZWG5LTONUW63RPGEYDGNJTGI3THJTSMVQXG33OVJZXKYTTMNZGSYTFMSSWK5TFNZ2KYZTPN52GK4S7MNWGSY3L>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BNLESQAKWJBJIIRLJVPIJA35CUOOZAVCNFSNUABGKJSXA33TNF2G64TZHMYTIOJRGE4TEO2ENFZWG5LTONUW63R3GEYDGNJTGI3THILWAI>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
|
Beta Was this translation helpful? Give feedback.
1 reply
-
|
In short: Adding css classes has been requested multiple times and I don't think I will ever add this functionality. Background is that SVG and CSS are web only and alphaTab aims to ship same functionality across all platforms and render engines. For the future of alphaTab (e.g. a 2.0) I am not even sure if I will still ship a SVG renderer but fully rely on raster graphics only. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
First off — thank you for alphaTab. It's an impressively complete piece of engineering, and the SVG rendering path in particular has made things possible for me that I wouldn't have attempted otherwise. This is a "wouldn't it be nice" idea, not a complaint — happy for it to just sit here as a discussion, and totally understand if it's not a priority or not the direction you want to take things.
The idea
Right now, every SVG element alphaTab renders gets its
fill/strokefrom one nameddisplay.resourcesrole (mainGlyphColor,secondaryGlyphColor,staffLineColor,barSeparatorColor,barNumberColor,scoreInfoColor). I'd love a way to select "all elements colored via role X" directly from CSS — right now the only handle available is the literal color value itself.The workaround I've found: since there's no CSS hook for "this role" other than the literal
fill/strokevalue alphaTab assigns, one option is to write a CSS attribute selector that matches on that value directly — e.g.[fill="#ffe600"]if that's the realmainGlyphColor. A further refinement is to assign each role a placeholder RGB value with no relation to the real desired color, used purely as a stable matching key, and let a separate stylesheet substitute in the actual color afterward — that at least avoids re-touching CSS every time the real color changes. But either way, the same fragility applies: if two roles ever resolve to the same fill value, elements from both roles get picked up by the same CSS rule with no error or warning, silently merging their styling. And using a color as the thing you match against in order to change that same color feels inherently unintuitive — the selector doesn't encode any meaning about what the element actually is, just what it happens to look like right now.So the ask: it'd be great if alphaTab emitted a stable, documented CSS class on every SVG element indicating which
display.resourcesrole produced its color — something likeclass="at-role-mainGlyph",at-role-staffLine,at-role-barNumber. This wouldn't require any further semantic sub-splitting of a role — it'd just be a way to target the existing six roles from CSS directly, instead of matching on color values.What I found poking around the source (might be useful, might be missing context)
All SVG emission seems to funnel through one place:
SvgCanvas(packages/alphatab/src/platform/svg/SvgCanvas.ts), withCssFontSvgCanvashandling music-symbol glyphs. There's actually already precedent for this kind of thing —CssFontSvgCanvasalready wraps every music-symbol glyph inclass="at"unconditionally.Colors get assigned to
canvas.colorfrom a lot of call sites — I counted roughly 60+, across ~15 files, includingElementStyleHelper/ElementStyleScopeplus several renderer/glyph classes that set it directly. My first instinct was that this would mean a fairly invasive change. But it looks likeRenderingResourcesconstructs each of the six default colors as its own distinct object, and every call site assigns by reference rather than copying the value — so it seems like the canvas layer could determine the active role via reference-equality checks against the six knownRenderingResourcesfields, right at the point of emission, without touching any of those ~15 files. Per-element style overrides (the existingNoteSubElement/BeatSubElement.stylemechanism) produce distinctColorobjects, so they'd naturally fall through without a role class — which seems like the right behavior rather than a gap, though I'd defer to you on that.One likely blocker worth being upfront about: alphaTab actually has three render engines —
svg(CssFontSvgCanvas),skia(SkiaCanvas), andhtml5(Html5Canvas, browser Canvas 2D). Theskiaandhtml5engines both draw to a raster canvas with no per-element output at all — there's nothing aclassattribute could attach to in that model. So this proposal is inherently SVG-only, not something that could be extended to the other backends later — it's a structural property of canvas rendering, not a missing feature there. If keeping capability parity across render engines is a design goal for alphaTab, that alone might be a reason to decline this, and I'd understand if so — just wanted to flag it rather than have it come up as a surprise.One other thing I couldn't verify: given the
transpilerpackage in the repo, I'm guessing the C#/Kotlin SVG output is generated from this TypeScript source rather than hand-maintained separately, so this would hopefully propagate for free — but I could easily be wrong about that.If I'm reading it right, this looks like it could be a fairly small, low-risk, mostly-one-file change, with a pattern that already exists elsewhere in the codebase — but you'd obviously know far better than I would whether that's actually true once you get into it.
Related discussion
I came across #1048 ("Dark mode score rendering") and #1558 ("Is it possible to customize appearance?") while searching — #1048 is about switching whole color presets, and #1558 is about API ergonomics for constructing
Color/Fontinstances. Neither seemed to cover this specifically, but flagging them in case I've missed the connection.If this is something you'd want on the roadmap, I'd be happy to put together a pull request for it myself — just let me know and I'll get started.
Thanks for reading this far, and for everything you've built here either way!
Beta Was this translation helpful? Give feedback.
All reactions