web components - html -javascript
TL;DR
This blogpost is about the power of HTML
Live Examples: https://olympic-medal-ranking.github.io/
Olympics Data API by Kevin Le
GitHub Kevle1 - endpointAll country SVG flags displayed by one 30 KB file
GitHub FlagMeisterOne Web Component displays the whole Olympic Medal Ranking table
GitHub<olympic-medal-ranking>
The <olympic-medal-ranking> Web Component
Web Components/Custom Elements technology is standard technology available in all modern browsers.
Web Components are not a toy for developers and can't be compared to other technologies
Web Components give power to HTML users! 💪🏽
The terms Web Component and Custom Elements are used interchangeably
Web Components encompass multiple technologies, whereas Custom Elements specifically refer to the API for defining new HTML elements.
All HTML required is:
<script src="https://olympic-medal-ranking.github.io/element.min.js"></script>
<olympic-medal-ranking></olympic-medal-ranking>
To display:
Flags are flags are flags?
Like many sites using flags, the Olympic site uses a PNG file for every country flag.
That is 56 files totalling a 103 KB (GZipped) download for the Olympic Medal Ranking page
The FlagMeister Web Component (since 2018)
Many moons ago I created a SINGLE 30 KB Web Component file de-hydrating all country flags as SVG (in IMG tags) (https://flagmeister.github.io/)
All HTML required is:
<script src="https://flagmeister.github.io/elements.flagmeister.min.js" />
<style>
img { width:100px; border: 1px solid grey }
</style>
<h1><flag-olympic></flag-olympic>Olympic Medal Ranking - Top 5</h1>
<flag-cn></flag-cn>
<flag-fr></flag-fr>
<flag-jp></flag-jp>
<flag-au></flag-au>
<flag-gb></flag-gb>
Every flag Web Component creates additional HTML:
Web Components are not like libraries/frameworks
It does not matter when the file defining the Web Component is loaded.
Using a <script>
tag it can be placed anywhere in the file.
A import
statement can be used at any time.
All existing undefined Elements in the DOM page will automagically upgrade.
Also see CSS :defined
- https://developer.mozilla.org/en-US/docs/Web/CSS/:defined
Olympics Data
Kevin Le simplified the Olympics Data API to a concise JSON format.
And, on request, within minutes, added ISO-3166-Alpha2 codes to match the flags. Because the IOC - International Olympic Committee uses their own Country Codes that do not 100% match with the ISO standard.
- GitHub: https://github.com/kevle1/paris-2024-olympic-api
- API Endpoint: https://api.olympics.kevle.xyz/medals?iso_codes=true
The Olympics Medal Rank Web Component
We got Flags and Medal Data;
now a new Web Component can create a Medal Ranking
- fetch Kevin Le's JSON endpoint
- loop all records
- display rank, flag, countryname & medal count
All HTML required is:
<script src="https://olympic-medal-ranking.github.io/element.min.js"></script>
<olympic-medal-ranking></olympic-medal-ranking>
The Web Component creates HTML in a shadowDOM/shadowRoot
Web Components can use Shadow DOM to encapsulate content, protecting against global styling and conflicting ID values. This keeps the CSS concise and the HTML code clean, ensuring the Web Component remains small and efficient.
You can not style shadowDOM with Global CSS!
Bollocks!
You can style shadowDOM, but only the parts the Web Component Author allows you to style with part
attributes:
<tr id="CHN" title="China">
<td class="rank" part="rank">1</td>
<td class="flag"><flag-cn is="flag-cn" alt="China">...</flag-cn></td>
<td part="countrycode"> CHN</td>
<td part="countryname">China</td>
<td class="medals gold" part="medal medalgold">11</td>
<td class="medals silver" part="medal medalsilver">7</td>
<td class="medals bronze" part="medal medalbronze">3</td>
<td class="medals total" part="medal medaltotal">21</td>
</tr>
So if the Web Component Author has added plenty of part
attributes,
you can use Global CSS
<style id="PARTS">
olympic-medal-ranking {
&::part(table) {
max-width: 550px;
}
&::part(header) {
font-size: 150%;
color: goldenrod;
background: lightgrey;
text-shadow: 1px 1px 1px black;
}
&::part(medal) {
font-weight: bold;
}
&::part(rank),
&::part(countrycode),
&::part(medaltotal) {
font-weight: normal;
color: grey;
}
}
</style>
Note:
shadowDOM is well over a decade old now.
All <input>
, <textarea>
, <video>
(and more) tags have been using shadowDOM under the hood for many years.
This is a browser-vendor-only version of shadowDOM called user-agent shadowDOM, and can not be styled by Global CSS (unless the Browser Vendor has programmed extra hooks for styling)
You can view all User-Agent shadowDOM by activating the console setting:
A filtered ranking for European Union countries
Can be created with HTML attributes flag
, total
and iocfilter
<olympic-medal-ranking
flag="EU"
total="all"
iocfilter="AUT,BEL,BUL,CRO,CYP,CZE,DEN,EST,FIN,FRA,GER,GRE,HUN,IRL,ITA,LAT,LTU,LUX,MLT,NED,POL,POR,ROU,SVK,SLO,ESP,SWE"
>European Union Medal Ranking</olympic-medal-ranking>
And EU styling for the <thead>
<style>
olympic-medal-ranking[flag="EU"] {
&::part(thead) {
background: #003399;
}
&::part(header) {
background: inherit;
color: gold;
font-weight: bold;
}
}
</style>
If you do want the source...
This was it, a blog-post for HTML Users, no JavaScript code displayed
The Web Component source code is at:
https://github.com/olympic-medal-ranking/olympic-medal-ranking.github.io
It has the Unlicense; so you can do whatever you want with it
Or fork the JSFiddle with JavaScript source for the Component:
Top comments (2)
Excellent idea. I really like web component too!
I usually prefer custom css to provide customization, but parts offers a nice flexibility for the consumer. What framework did you use to build your web component?
None, I am one of those farmers who understands nature and doesn't use pesticides, additives or antibiotics
Native code in the blogpost is all that is required