bolino
bolino

Reputation: 1122

Get the layout size of child components in Svelte

I'm converting a VanillaJS website to Svelte, where it's needed to have divs randomly positioned on the webpage. Note that each of the div size can vary according to their content, they cannot have fixed size in their CSS.

I can easily calculate a random top and left position for each div with the the window size as the maximum, and send it as props to each of the div, using it in inline style. But I don't know how to subtract the calculated size of each div, so that the top-left position would not sometimes place the div partly out of the windows screen.

In Vanilla JS I was using offsetWidth and offsetHeight to get the calculated size of the divs as there were HTMLElement types, but it doesn't work in Svelte: I get the error Property 'offsetHeight' does not exist on type 'Element'.

Any idea on how I can achieve that?

Here is the code for the main App.svelte:

<script>
  import Window from "./components/Div.svelte";

  const left = Math.random() * window.innerWidth; // TODO substract div width
  const top = Math.random() * window.innerHeight; // TODO substract div height

  // THIS IS NOT WORKING
  // const el = document.querySelector('#my-div')
  // const left = Math.round(Math.random() * (window.innerWidth - el.offsetWidth))
  // const top = Math.round(Math.random() * (window.innerHeight - el.offsetHeight))

</script>

<main>
  <Div
    divName="my-div"
    top={top}px
    left={left}px
    htmlContent="My HTML content with <strong>bold text</strong> and <em>italicized text</em>."
  />
</main>

...and this is on div subcomponent Div.svelte:

<script>
    export let divName;
    export let top;
    export let left;
    export let htmlContent;
</script>

<div id={divName} class="div" style="top: {top}; left: {left};">
    <h1>{divName}</h1>
    <article>{@html htmlContent}</article>
</div>

<style>
    .div {
        min-width: 250px;
        max-width: 600px;
        position: absolute;
        background-color: red;
    }
</style>

Upvotes: 1

Views: 1466

Answers (1)

Jos&#233; Ram&#237;rez
Jos&#233; Ram&#237;rez

Reputation: 2360

It is possible to get the div's dimensions, yes. It is done in a very sveltey way as taught here.

<script>
    export let divName;
    export let top;
    export let left;
    export let htmlContent;

    export let width;
    export let height;
</script>

<div
    id={divName}
    class="div"
    style="top: {top}; left: {left};"
    bind:clientWidth={width}
    bind:clientHeight={height}
>
    <h1>{divName}</h1>
    <article>{@html htmlContent}</article>
</div>

<style>
    .div {
        min-width: 250px;
        max-width: 600px;
        position: absolute;
        background-color: red;
    }
</style>

This modification I present to you binds 2 props to the dimensions of the DIV. This means that its parent component can bind to said props as taught here.

For your particular case of adjusting top and left, maybe you don't need to export the dimensions. Maybe you can just handle the repositioning inside the DIV component. You can treat the top and left props as "initial" position values, and then have your component auto-correct its position based on the dimensions. Your choice.

Upvotes: 3

Related Questions