Height and width of an html div

Is there a way to obtain the height and width of a dash html div? I have a dcc.Graph figure housed within a html.Div element, and even though I have specified the dimensions of the Graph figure, I checked the end coordinates using EventListener and it seems smaller. For instance, in the image, I clicked at almost the bottom right of the div, and the height displayed is much less even though the width is correct.

This was the code I used to create this application:

from dash import Dash, html, dcc, Input, Output, State
import plotly.graph_objects as go
import pandas as pd
import json
from dash_extensions import EventListener

base_url = "https://raw.githubusercontent.com/plotly/datasets/master/ply/sandal"
dataframe = pd.read_csv(base_url + '-ply.csv') 

app = Dash(
    __name__,
    external_stylesheets=[
        "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css",
    ]
)

app.layout = html.Div(
    [
        html.Div(
            className='col-6',
            children=EventListener(
                html.Div([
                    dcc.Graph(
                        id='graph',
                    ),
                ],
                    style={
                        'border-width': '1px',
                        'border-style': 'solid',
                        'border-color': 'black'
                    }
                ),
                events=[{"event": "click", "props": ['x', 'y']}],
                logging=True,
                id="event_listener"
            )
        ),
        html.Div(
            id='out_0',
            className='col-2'
        ),
        html.Div(
            id='out_1',
            className='col-2'
        ),
    ],
    className='row'
)


@app.callback(
    Output('graph', 'figure'),
    Output('out_0', 'children'),
    Output('out_1', 'children'),
    Input('graph', 'clickData'),
    Input('event_listener', 'n_events'),
    State('event_listener', 'event'),
)
def update(click_data, _n_events, event):
    df = dataframe

    fig = go.Figure(data=go.Mesh3d(
        x=df.x, y=df.y, z=df.z, 
        i=df.i, j=df.j, k=df.k, 
        facecolor=df.facecolor),
        layout=dict(
            scene={
                "xaxis": {
                    'showgrid': False,
                    'zeroline': False,
                    'visible': False,
                    "range": [df.x.min(), df.x.max()]
                },
                "yaxis": {
                    'showgrid': False,
                    'zeroline': False,
                    'visible': False,
                    "range": [df.y.min(), df.y.max()]
                },
                "zaxis": {
                    'showgrid': False,
                    'zeroline': False,
                    'visible': False,
                    "range": [df.z.min(), df.z.max()]
                },
            },
            autosize=False,
            width=750, height=1000,
            scene_camera=dict(
                up=dict(x=0, y=1, z=0),
                center=dict(x=0, y=0, z=0),
                eye=dict(x=df.x.mean(), y=0, z=5),
                projection=dict(type='perspective')),
            scene_aspectmode="data",
            clickmode="event+select",
            margin={'l': 0, 't': 0})
    )
    return [
        fig,
        html.Pre([html.H5('click data mesh'), json.dumps(click_data, indent=3)]),
        html.Pre([html.H5('event listener'), json.dumps(event, indent=3)]),
    ]


if __name__ == "__main__":
    app.run(debug=True)

Is there a way to accurately obtain the dimensions of the graph div?

Hi @ac13 ,

As far as I know, there is two options that you can do to obtain actual x,y values from click event.

First option:
To view your actual size of div, try to zoom out the browser (not zoom out the plot) until 50% (or you can try smaller).
When you click the div, it will show your expected dimension.

Second option:
another way, if you you use windows system and default resolution is 1920x1080, try to change Display Scaling at 100%. (in windows 11 by default will be 150%).
With second option just need make sure to full screen the browser or zoom out the browser at 80%-90%.

hope this help.

Hello, thanks for the response!
On zooming out the browser, the height does match but the width overshoots the expected value.

Is there an automated way to obtain the current height and width within the code, say in a callback, since the width and height specified in the figure layout does not seem to be followed (one matches while the other doesn’t)?

Hi @ac13 ,

I think pageX and pageY is the props that you are looking for:

The pageX read-only property of the MouseEvent interface returns the X (horizontal) coordinate (in pixels) at which the mouse was clicked, relative to the left edge of the entire document. This includes any portion of the document not currently visible.

The pageY read-only property of the MouseEvent interface returns the Y (vertical) coordinate in pixels of the event relative to the whole document. This property takes into account any vertical scrolling of the page.

Try to add pageX and pageY on your props

... 
 html.Div(
            className='col-6',
            children=EventListener(
                html.Div([
                    dcc.Graph(
                        id='graph',
                    ),
                ],
                    style={
                        'border-width': '1px',
                        'border-style': 'solid',
                        'border-color': 'black'
                    }
                ),
                events=[{"event": "click", "props": ['x', 'y','pageX','pageY']}],
                logging=True,
                id="event_listener"
            )
        ),
...

if this is works fine , then you don’t need to zoom out the browser.

cheers.

Hello, thanks for the response. This is useful.
But, I was looking for the height and width of the div (not just the coordinates of the position of the mouse click event). I had set them to 1000 and 750 respectively, but the coordinates of the bottom right corner don’t match those values.
My goal is to obtain normalized coordinates of the position of the mouse click (using this and the camera, I would unproject it to 3D coordinates), for which I need the total height and width of the div.

Hi @ac13 ,

Okay, let me try again … :slightly_smiling_face:

Have you tried to set the max-width and max-heightfor the Div component based on your Figure size?
Make the size of Figure same as Div.

Also, I gave background color yellow to Figure, make it easier to click the coordinates of the bottom right corner.

Here the modified code based on your code earlier.

from dash import Dash, html, dcc, Input, Output, State
import plotly.graph_objects as go
import pandas as pd
import json
from dash_extensions import EventListener

base_url = "https://raw.githubusercontent.com/plotly/datasets/master/ply/sandal"
dataframe = pd.read_csv(base_url + '-ply.csv') 

app = Dash(
    __name__,
    external_stylesheets=[
        "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css",
    ]
)

app.layout = html.Div(
    [
        html.Div(
            className='col-6',
            children=EventListener(
                html.Div([
                    dcc.Graph(
                        id='graph',
                    ),
                ],
                    style={
                        'border-width': '1px',
                        'border-style': 'solid',
                        'border-color': 'black',
                        # Setting max width, max height and margin bottom.
                        'max-width': '750px',
                        'max-height': '1000px',
                        'margin-bottom':'50px',
                        
                    }
                ),
                events=[{"event": "click", "props": ['x', 'y','pageX','pageY']}],
                logging=True,
                id="event_listener"
            ),
        ),
        html.Div(
            id='out_0',
            className='col-2'
        ),
        html.Div(
            id='out_1',
            className='col-2'
        ),
    ],
    className='row',
    style={
        'height': '100vh',
    }
)


@app.callback(
    Output('graph', 'figure'),
    Output('out_0', 'children'),
    Output('out_1', 'children'),
    Input('graph', 'clickData'),
    Input('event_listener', 'n_events'),
    State('event_listener', 'event'),
)
def update(click_data, _n_events, event):
    df = dataframe

    fig = go.Figure(data=go.Mesh3d(
        x=df.x, y=df.y, z=df.z, 
        i=df.i, j=df.j, k=df.k, 
        facecolor=df.facecolor),
        layout=dict(
            plot_bgcolor = "yellow",
            paper_bgcolor ="yellow", # coloring  yellow to the backgroun d make easier to click. 
            scene={
                "xaxis": {
                    'showgrid': False,
                    'zeroline': False,
                    'visible': False,
                    "range": [df.x.min(), df.x.max()]
                },
                "yaxis": {
                    'showgrid': False,
                    'zeroline': False,
                    'visible': False,
                    "range": [df.y.min(), df.y.max()]
                },
                "zaxis": {
                    'showgrid': False,
                    'zeroline': False,
                    'visible': False,
                    "range": [df.z.min(), df.z.max()]
                },
            },
            autosize=False,
            width=750, height=1000,
            scene_camera=dict(
                up=dict(x=0, y=1, z=0),
                center=dict(x=0, y=0, z=0),
                eye=dict(x=df.x.mean(), y=0, z=5),
                projection=dict(type='perspective')),
            scene_aspectmode="data",
            clickmode="event+select",
            margin={'l': 0, 't': 0})
    )
    return [
        fig,
        html.Pre([html.H5('click data mesh'), json.dumps(click_data, indent=3)]),
        html.Pre([html.H5('event listener'), json.dumps(event, indent=3)]),
    ]


if __name__ == "__main__":
    app.run(debug=True)

This is what I get when I click in the bottom right corner of yellow area (which mean div area).

the values of right bottom corner is pageX : 750 and pageY: 1000.

1 Like

Awesome, that works!
Thanks a lot :grin:

1 Like