Styling out-of-the-box widgets in Experience Builder with CSS selectors

235
4
03-21-2024 11:37 AM
AndrewAlbers
New Contributor II

I'm building an app in Experience Builder for a client who wants to style out-of-the-box widgets as much as possible and avoid custom components for the sake of maintainability. For example: here's an out-of-the-box filter (on the left) compared to the same filter with styling and style.scss provided by a custom theme:

slide_toggle_css.gif

The style.scss code for the filter relies on identifying descendants of the widget's data-widgetid:

div[data-widgetid="widget_116"] .filter-items-container,
div[data-widgetid="widget_116"] .filter-item,
div[data-widgetid="widget_116"] .filter-item-inline {
  border: none;
  overflow: visible;
}
div[data-widgetid="widget_116"] .filter-item-icon, div[data-widgetid="widget_116"] .filter-item-name {
  display: none;
}
div[data-widgetid="widget_116"] .overflow-auto {
  overflow: visible !important;
}
div[data-widgetid="widget_116"] .switch-slider {
  height: 20px;
  width: 50px;
  color: var(--light);
  background: var(--primary);
  border-radius: 10px;
  overflow: visible;
}
div[data-widgetid="widget_116"] .jimu-switch:not(.checked)::after {
  content: "2023";
  margin: auto;
  font-size: medium;
}
div[data-widgetid="widget_116"] .checked .jimu-switch::after {
  content: none;
  font-size: medium;
}
div[data-widgetid="widget_116"] span.jimu-switch.checked::before {
  position: absolute;
  width: 50px;
  content: "2019";
  padding-left: 10px;
  font-size: medium;
}
div[data-widgetid="widget_116"] span.switch-slider {
  text-align: center;
  font-size: medium;
}
div[data-widgetid="widget_116"] .switch-slider::before {
  content: "2019";
}
div[data-widgetid="widget_116"] .checked .switch-slider {
  background: var(--primary);
  color: var(--light);
}
div[data-widgetid="widget_116"] .checked .switch-slider::before {
  content: "2023";
}
div[data-widgetid="widget_116"] .jimu-switch {
  width: 100px;
  height: 20px;
  padding: 0;
  border: none;
  border-radius: 10px;
  background: var(--light-200);
}
div[data-widgetid="widget_116"] .checked .switch-slider {
  margin-left: 50px;
}


I think I can match the client's desired mockup pretty closely with pure CSS this way, but I worry since these data-widgetid values are related to the order in which widgets are added to the experience. That means deleting and re-creating a widget is going to necessitate updating the CSS selectors in style.scss.

Is there any better way to select specific widgets with css than the way I'm doing it? Is there any other attribute that could be used as a css selector?  Ideally it'd be nice if widgets could be selected via css using the name given to them in the outline, but this doesn't seem to affect anything in the app DOM.

0 Kudos
4 Replies
KeithWestberg
New Contributor II

This comes with a full ignorance to most things ESRI disclaimer.  Do you have access at all to the PARENT div, which is the dive that you are referencing with data-widgetid?  Asked another way, does this environment give you anything at all to bite onto besides teh data titled reference?  Not knowing the terrain, and purely on assumption, you could use css navigation to ding the PARENT element.  So in a perfect world with only one DIV to compete with, when mixed with many of these css classes, instead of this:

div[data-widgetid="widget_116"] .overflow-auto {
  display: none; }

you could try:

div[data-widgetid] .overflow-auto {
  display: none; } 

worth kicking the tires  =]

 

0 Kudos
KeithWestberg
New Contributor II

After rereading your comment, it appears you're looking at many widgets to compete with, so my earlier comment falls flat.  You also can't walk up the element tree by referencing parent, because anything parent to the class .overflow-auto would be subject to your whim.  So, in retrospect, without the environment giving you a method of either adding a global class to the widget, or its position in the rendering que, it appears you're in a pickle.

0 Kudos
KeithWestberg
New Contributor II

if you CAN add a class to the parent DIV that contains the data-widgetid, then you could reference DIV.myAmazingPersonalClass .overflow-auto

 

0 Kudos
AndrewAlbers
New Contributor II

@KeithWestberg I guess that's part of my question: Is there any way to add a custom-defined class to the top-level div for each widget so I have something consistent and descriptive to grab onto?

0 Kudos