<popup-info>
About using external CSS styles
Note that <link>
elements do not block paint of the shadow root, so there may be a flash of unstyled content (FOUC) while the stylesheet loads.
/*
Using Shadow DOM
https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_shadow_DOM
*/
// ⭐️ 1. custom web component
class PopUpInfo extends HTMLElement {
// constructor
constructor() {
// tell HTMLElement to initialize itself.
super();
// Create a shadow root
let shadow = this.attachShadow({mode: 'open'});
// get attributes from this <popup-info>
let info = this.getAttribute('data-text');
let src = this.getAttribute('img') ?? 'https://mdn.github.io/web-components-examples/popup-info-box-web-component/img/alt.png';
// set the shadow tree
shadow.innerHTML = PopUpInfo.template(src, info);
}
// template HTML (⭐️ external css styles)
static template(imgURL, infoText){
return `
<link href="popup.css" rel="stylesheet" />
<span class="wrapper">
<span class="icon" tabindex=0>
<img src="${imgURL}">
</span>
<span class="info">${infoText}</span>
</span>
`;
}
}
// ⭐️ 2. define custom tag <popup-info>
// ⭐️⭐️ custom element names must contain a "hyphen".
customElements.define('popup-info', PopUpInfo);
// ⭐️ 1. custom web component
class PopUpInfo extends HTMLElement {
// constructor
constructor() {
// tell HTMLElement to initialize itself.
super();
// Create a shadow root
let shadow = this.attachShadow({mode: 'open'});
// get attributes from this <popup-info>
let info = this.getAttribute('data-text');
let src = this.getAttribute('img') ?? 'https://mdn.github.io/web-components-examples/popup-info-box-web-component/img/alt.png';
// set the shadow tree
shadow.innerHTML = PopUpInfo.template(src, info);
}
// template HTML (domString)
static template(imgURL, infoText){
return `
<style>
.wrapper {
position: relative;
}
.info {
font-size: 0.8rem;
width: 200px;
display: inline-block;
border: 1px solid black;
padding: 10px;
background: hsla(60, 80%, 50%, 0.9);
border-radius: 10px;
opacity: 0;
transition: 0.6s all;
position: absolute;
top: 20px;
left: 10px;
z-index: 3;
}
img {
width: 1.2rem;
}
.icon:hover + .info, .icon:focus + .info {
opacity: 1;
}
</style>
<span class="wrapper">
<span class="icon" tabindex=0>
<img src="${imgURL}">
</span>
<span class="info">${infoText}</span>
</span>
`;
}
}
// ⭐️ 2. define custom tag <popup-info>
// ⭐️⭐️ custom element names must contain a "hyphen".
customElements.define('popup-info', PopUpInfo);
.wrapper {
position: relative;
}
.info {
font-size: 0.8rem;
width: 200px;
display: inline-block;
border: 1px solid black;
padding: 10px;
background: hsla(60, 80%, 50%, 0.9);
border-radius: 10px;
opacity: 0;
transition: 0.6s all;
position: absolute;
top: 20px;
left: 10px;
z-index: 3;
}
img {
width: 1.2rem;
}
.icon:hover + .info, .icon:focus + .info {
opacity: 1;
}
// ⭐️ 1. custom web component
class PopUpInfo extends HTMLElement {
// constructor
constructor() {
// tell HTMLElement to initialize itself.
super();
// Create a shadow root
let shadow = this.attachShadow({mode: 'open'});
// create spans
let wrapper = tag('span', {'class': 'wrapper'});
let icon = tag('span', {'class': 'icon', 'tabindex': 0});
let info = tag('span', {'class': 'info'});
info.textContent = this.getAttribute('data-text');
// img
let src = this.getAttribute('img') ?? 'https://mdn.github.io/web-components-examples/popup-info-box-web-component/img/alt.png';
let img = tag('img', {'src': src});
icon.appendChild(img);
// attach elements to shadow dom // shadow root
shadow.appendChild(this.style()); // ├ style
shadow.appendChild(wrapper); // └ wrapper
wrapper.appendChild(icon); // ├ icon
wrapper.appendChild(info); // │ └ img
} // └ info
// css style
style() {
// Create some CSS to apply to the shadow dom
let style = document.createElement('style');
style.textContent = `
.wrapper {
position: relative;
}
.info {
font-size: 0.8rem;
width: 200px;
display: inline-block;
border: 1px solid black;
padding: 10px;
background: hsla(60, 80%, 50%, 0.9);
border-radius: 10px;
opacity: 0;
transition: 0.6s all;
position: absolute;
top: 20px;
left: 10px;
z-index: 3;
}
img {
width: 1.2rem;
}
.icon:hover + .info, .icon:focus + .info {
opacity: 1;
}`;
return style;
}
}
// ⭐️ 2. define custom tag <popup-info>
// ⭐️⭐️ custom element names must contain a "hyphen".
customElements.define('popup-info', PopUpInfo);
/* -------- helpers -------- */
function tag(name, attrs){
// create element
let elem = document.createElement(name);
// set attributes
for (const [key, value] of Object.entries(attrs)) {
elem.setAttribute(key, value);
}
// return element
return elem;
}
<p>Lorem ipsum dolor sit, amet consectetur adipisicing elit.
Autem, assumenda aut voluptas perspiciatis impedit alias.
Fugit atque eos voluptatem suscipit quos nostrum!
Libero tenetur deleniti minima! Atque laborum minima non.</p>
<!-- web component -->
<popup-info
img="https://mdn.github.io/web-components-examples/popup-info-box-web-component/img/alt.png"
data-text="Your card validation code (CVC) is an extra security feature — it is the last 3 or 4 numbers on the back of your card."
></popup-info>
<span>hover over this image.</span>
<h1>Hello</h1>
Last updated