marimo icon indicating copy to clipboard operation
marimo copied to clipboard

CSS styling not working for anywidget based widget in marimo

Open paddymul opened this issue 11 months ago • 1 comments

Describe the bug

I'm working on updating buckaroo to use anywidget. It renders to the dom in marimo, but the styling is really off. Some of my divs aren't the correct width

Does marimo do anything special to css included with an anywidget widget that I should know about

I put the orange border in that div. but the rest is scrunched up against the left side. Image Here is the same widget rendered in jupyter lab Image

I'm usre theres something that I can change in my code, I was curious if I was bumping up against a known bug. or there is a recommended workaround.

Environment

{
  "marimo": "0.10.8",
  "OS": "Darwin",
  "OS Version": "22.6.0",
  "Processor": "arm",
  "Python Version": "3.12.8",
  "Binaries": {
    "Browser": "131.0.6778.205",
    "Node": "v18.20.4"
  },
  "Dependencies": {
    "click": "8.1.8",
    "docutils": "0.21.2",
    "itsdangerous": "2.2.0",
    "jedi": "0.19.2",
    "markdown": "3.7",
    "narwhals": "1.19.1",
    "packaging": "24.2",
    "psutil": "5.9.0",
    "pygments": "2.18.0",
    "pymdown-extensions": "10.13",
    "pyyaml": "6.0.2",
    "ruff": "0.8.4",
    "starlette": "0.43.0",
    "tomlkit": "0.13.2",
    "typing-extensions": "4.12.2",
    "uvicorn": "0.34.0",
    "websockets": "14.1"
  },
  "Optional Dependencies": {
    "anywidget": "0.9.13",
    "pandas": "2.2.3",
    "polars": "1.18.0",
    "pyarrow": "17.0.0"
  }
}

Code to reproduce

pip install buckaroo

import pandas as pd
from buckaroo import BuckarooWidget
num_df = pd.DataFrame(
    {'a':[111_111,  77_777, 777_777, 1_000_000, 2_111_111, 1_235_999],
     'b':[111_111, 555_555,       0,    28_123,   482_388,     5_666]})
BuckarooWidget(num_df)

paddymul avatar Dec 30 '24 18:12 paddymul

We put our anywidget elements on shadow doms for better encapsulation of styling to avoid polluting the global namespace. That could be it, but not sure without looking into the stylesheets. I can take a look, if you can link them.

mscolnick avatar Dec 30 '24 23:12 mscolnick

Sorry, I missed this. I made some progress, I'm running into a different problem now, but still related to marimo. I'm not sure the best way to describe reproduction steps.

Currently Buckaroo inside marimo isn't picking up the same styles that it is in jupyter lab. The css is compiled / concatenated in the anywidget build step.

The core problem seems to come down to not picking up a theme from the included ag-grid styles

(marimo on the left, jupyter on the right. notice the lack of dark background in marimo). Image

The css for both platforms is the same because that is the only css in the buckaroo wheel. The injected dom classes seem to be identical. To look at the bundled css you can follow theses steps. Sorry if this is an awkward way to describe reproduction

curl https://files.pythonhosted.org/packages/bd/a6/793ceddd4bda93ec2ef5bb61c09d9823386aaff46169ff1170b79c88df66/buckaroo-0.8.3-py3-none-any.whl > buckaroo-0.8.3-py3-none-any.whl
tar xvzf buckaroo-0.8.2-py3-none-any.whl
cat buckaroo/static/widget.css | grep .ag-theme-alpine-dark | wc -l

this shows that widget.css includes css referencing .ag-theme-alpine-dark

the selectors for .ag-theme-alpine-dark class isn't prefixed by any other selector from what I can see (discounting the possibility of a different parent div name in marimo vs jupyter.

I'm talking through possible explanations for the different styling, but right now I'm drawing a blank.

Happy to try other approaches, hopefully this bug will be useful to future devs that want to build for marimo

paddymul avatar Jan 27 '25 21:01 paddymul

@paddymul this is likely still because of the shadowdom. the ag styles might be being placed on the global css scope and are not passed to the shadowdom. how are you importing these styles? are you using the _css prop from anywidget?

mscolnick avatar Jan 27 '25 21:01 mscolnick

yes I am using the _css prop. What should I use instead?

paddymul avatar Jan 27 '25 21:01 paddymul

A sample anywidget with different types of css inclusion, and how they behave in marimo vs jupyter would be helpful.

paddymul avatar Jan 27 '25 21:01 paddymul

Using the _css prop is correct. I dont have sample anywidgets, but there are plenty on this page: https://anywidget.dev/en/community/

mscolnick avatar Jan 27 '25 23:01 mscolnick

If you can share the code or a reproduction, i am happy to take a look

mscolnick avatar Jan 27 '25 23:01 mscolnick

Ok. I will make some examples and play with some stuff to see what works and what doesn't soon.

paddymul avatar Jan 27 '25 23:01 paddymul

I have tried a series of debugging steps

Steps I tried included

  • trying the basic anywidget example. which worked.
  • pointing the BuckarooWidget._css at a hard coded fully specified path file which displayed exactly as the BuckarooWidget was displaying, I wanted to verify that it wasn't some type of packaging issue.
  • editting that hardcoded file to put some borders around elements I could see inside the shadow dom. This worked
  • putting the border debugging at different points in the 7000 line file, still worked
  • carefully inspecting the css as applied to elements. I think I found something here.

Here are screenshots from the dom inspector.

Image Image

constructed.css seems to come from marimo, inline comes from Buckaroo. You can see that all relevant styles other than the blue border (which does display) are dashed out meaning they aren't applied

It looks like marimo also includes ag-grid based styling. https://github.com/marimo-team/marimo/blob/33d6e58487b4d5fa5801b8a0b300bd0fecbd35a4/frontend/package.json#L87-L88 Marimo points at ag-grid 32.2.2, Buckaroo uses ag-grid 32.3.2 . bumping buckaroo back to 32.2.2 didn't fix the problem

Do you have any recommendations to give the Buckaroo css priority?

paddymul avatar Jan 28 '25 13:01 paddymul

Yes this is definitely the conflict.

My div with ag-theme-alpine-dark looks like this

        <div className={`df-viewer  ${hs.classMode} ${hs.inIframe}`}>
            <div style={hs.applicableStyle} className={`theme-hanger ag-theme-alpine-dark`}>
                <AgGridReact

I updated a single rule in the anywidget referenced stylesheet to add theme-hanger

.theme-hanger.ag-theme-alpine-dark {
    border:5px solid orange;
  --ag-background-color: #181d1f;
  --ag-foreground-color: #fff;

Because of increased specificity that rule took precedence.

paddymul avatar Jan 28 '25 14:01 paddymul

Sorry for being overly verbose. It helps to keep track of things I have tried, while writing this, I thought of other approaches to try.

I guess the generic question is: How do I make sure that css injected from anywidget has precedence over any other rules from the outer page.

Is there a setting or attribute on the shadowDOM? Would you recommend a CSS build step? Something else obvious?

paddymul avatar Jan 28 '25 14:01 paddymul

I see, our ag-grid styles shouldn't pollute the global CSS. I have a fix for that here: https://github.com/marimo-team/marimo/pull/3601. I also made the anywidget CSS styles use constructed style sheets (and come last) so they take precedence.

If you are running marimo locally, can you let me know if this fixes it. If not, I plan to release today

mscolnick avatar Jan 28 '25 14:01 mscolnick

I pulled the most recent main, and that fixes the problem. Thanks for the quick response, and bearing with me as I debug it.

There are still some other styling issues, but I will assume they are on my end, until I do more research.

Image

paddymul avatar Jan 28 '25 15:01 paddymul

awesome, glad it works! let me know if I can help debug further with the CSS changes. (here or Discord)

mscolnick avatar Jan 28 '25 15:01 mscolnick