0

I'm working on some custom blocks for a theme, and I have the following edit code to create a column that goes inside a flex container:

function EditComponent({ attributes, setAttributes }) {
  const blockProps = useBlockProps({});
  const innerBlockProps = useInnerBlocksProps(blockProps);
  return (
    <>
      <InspectorControls>
        <PanelBody title="Width" initialOpen={false}>
          <PanelRow>
            <UnitControl
              value={attributes.width}
              label="Column Width"
              onChange={(val) => setAttributes({ width: val })}
            />
          </PanelRow>
        </PanelBody>
      </InspectorControls>
      <div
        {...innerBlockProps}
        style={{
          width: attributes.width,
        }}
      ></div>
    </>
  );
}

This works fine if I set the column width in an absolute value like rem or px. However, if I try to set width in percentage, it breaks (only in the editor) because the editor is adding a wrapper width class .block-editor-block-list__block between the column and its parent. Is there anything I can do to either remove this wrapper or pass the width value up to it so I can get a correct layout in the editor? Thanks.

1 Answer 1

2

Leaving this open in case anyone has a cleaner answer, but just wanted to capture what I ended up going with for the time being. Looking at how Wordpress handles some of their native blocks, it looks like they set the parent editor wrapper's width imperatively in px, even when its set by the user in percent. Keeping with this framework, I decided to do a bit of imperative stuff in the component, as follows:

function EditComponent({ attributes, setAttributes }) {
  const width = useWindowWidth();
  const blockProps = useBlockProps({});
  const innerBlockProps = useInnerBlocksProps(blockProps);
  const divRef = useRef();

  useEffect(() => {
    var wrapper = thisRef.current.parentNode;
    var widthReference = wrapper.parentNode;
    var widthToSet =
      width > 1024
        ? attributes.large.width
        : width > 768
        ? attributes.medium.width
        : attributes.small.width;
    if (!widthToSet.includes("%")) return;
    var widthPercent = parseInt(widthToSet.replace("%", "")) / 100;
    setEditorWidthInPx(
      widthReference.getBoundingClientRect().width * widthPercent
    );
  }, [width, attributes]);

  return (
    <>
      <InspectorControls>
        <PanelBody title="Width" initialOpen={false}>
          <PanelRow>
            <UnitControl
              value={attributes.small.width}
              label="Column Width"
              onChange={(val) => setAttributes({ width: val })}
            />
          </PanelRow>
        </PanelBody>
      </InspectorControls>
      <div
        ref={divRef}
        {...innerBlockProps}
        style={{
          width: attributes.width,
        }}
      ></div>
    </>
  );
}

My useEffect watches both the window's width and the attributes, and on any changes, it grabs the column element, its parent and its grandparent, grabs the width value, and if it's in percent, calculates the pixel value relative to the grandparent container and manually sets the element's width in pixels.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.