I am making a custom element that functions as a textarea with syntax highlighting and some other features. I’ve simplified it to a custom element with a div inside that gains height when clicking the page.
To make the custom element have a default height and be able to increase in height due to more content, I used min-height: 40vh
. The problem is that height: 100%
in the div inside the shadow dom doesn’t work. It doesn’t expand to 100% of the height of the shadow dom / the custom element’s inner height. However, the custom element does still grow to fit the div when needed.
Note that the custom element uses box-sizing: border-box
and also has a border.
What I have tried:
I have tried all these on both Chrome and Firefox and none of them work as desired on either browser.
height: anything between 0 and 40vh
on custom element
This works except the custom element doesn’t grow to fit the div when the div grows bigger than the custom element.
min-height: inherit
on div
This works except it includes the border of the custom element parent, which makes the parent grow bigger than 40vh by default using box-sizing: border-box
. I want the custom element to have min-height: 40vh
with box-sizing: border-box
.
Flexbox
Flexbox on the custom element doesn’t affect elements in the shadow root.
The code with the problem
Note that StackOverflow doesn’t give the snippet enough screen height to show the problem, and clicking "Expand snippet" and then running it has the same problem, so make sure to first start it and then click "Full page", and then clicking the page will make the div grow.
<!DOCTYPE html>
<html>
<head>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
html, body {
height: 100%;
}
my-element {
border: 40px solid gray;
min-height: 40vh;
}
</style>
</head>
<body>
<my-element></my-element>
<script>
class MyElement extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: "open" });
const stylesheet = new CSSStyleSheet();
stylesheet.replaceSync(`
* {
margin: 0;
padding: 0;
}
:host {
display: block;
}
div {
background: green;
width: 100%;
height: 100%; /* not working */
}
`);
shadow.adoptedStyleSheets = [stylesheet];
const div = document.createElement("div");
div.innerText = "Hello";
shadow.appendChild(div);
document.body.onclick = () => {
div.innerText += "nHi";
};
}
}
customElements.define("my-element", MyElement);
</script>
</body>
</html>
I could make a hacky solution using JS but I want to see if there is a way to do this using just CSS.
2
Answers
Your
div
is occupying 100% of the height of its parent element, which ismy-element
. If you want it to occupy the entirety of the screen, then you will need to set its parent to have 100% height.If it can’t be done with pure CSS, and you do need JavaScript,
then I would toggle a
<STYLE>
inside shadowDOMIf the content is less than the Component
clientHeight
enable that<STYLE>
When the content overflows the Web Component, disable the
<STYLE>
This way you can add more styling (
border-color:blue
in below example)And you are not sticking inline styles on an element.
https://jsfiddle.net/WebComponents/w704hdvu/
I refactored your code so it can run as inline SO snippet
Initial state of the
<STYLE>
is disabled to show the RED background.After first click it shows correct state.