reactjs - Kunde inte använda CSS på React-portalens innehåll


Jag försöker använda React-portal för att rendera en portal, så jag skapade två div: en för bakgrund och en för själva portalen inne i index.html-filen.

 <div id="backdrop-root"></div>
 <div id="overlay-root"></div>
 <div id="root"></div>

Min portalkod:

const Backdrop = () => {
  return <div className="backdrop" />;
};
const ModalOverlay = () => {

  return (
    <div css={NewTransactionPortalStyles} className="modal">
      <Card>
        <div className="modal-header">
          <div>Create Transaction</div>
          <div>
            <XLg size={23} />
          </div>
        </div>
        <div className="grid-styles">
          <div> This is my Portal </div>
        </div>
      </Card>
    </div>
  );
};

export const NewTransactionPortal = () => {
  return (
    <div css={NewTransactionPortalStyles}>
      {ReactDOM.createPortal(
        <Backdrop />,
        document.getElementById("backdrop-root")!
      )}
      {ReactDOM.createPortal(
        <ModalOverlay transaction={[]} />,
        document.getElementById("overlay-root")!
      )}
    </div>
  );

CSS-innehåll:

export const NewTransactionPortalStyles = css`
    .backdrop {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100vh;
      z-index: 10;
      background: rgba(0, 0, 0, 0.75);
    }

    .modal {
      position: fixed;
      top: 30vh;
      left: 10%;
      width: 60%;
      height: 50%
      z-index: 100;
      overflow: hidden;
    }

Jag vet inte vad som saknas men min CSS-klass tillämpas inte på min portal, jag kan se att jag kan rikta in mig på div:en men kan inte tillämpa CSS på den, så som ett resultat kan jag inte få önskat resultat. Jag använder Emotion-biblioteket för min CSS här.

Svar #1

Jag stötte på ett liknande problem med mitt projekt. Tyvärr var det mesta av min CSS global och inkluderad i JS-filen istället för att tilldelas på komponentnivå. Vad jag slutade göra var helt enkelt att sätta innerHTML för head-taggen på fönstret till den jag använde för huvudfönstret:

const NewWindow = ({ children }) => {
  const newWindow = React.useMemo(() => window.open('', 'New Window'), [children]);
  newWindow.document.head.innerHTML = window.document.head.innerHTML;
  return ReactDOM.createPortal(children, newWindow.document.body);
};

Kan eller kanske inte vara tillämpligt på ditt användningsfall dock.

Svar #2

När man använder React Portal är portalens innehåll faktiskt på en annan DOM-position än vad man kan sluta sig till från React-komponenternas träd: portalens innehåll placeras som en av den angivna elementets efterkommande.

Detta kan ses i din skärmdump:

  • backdrop-diven är ett barn till backdrop-root
  • modal är ett barn till overlay-root
  • båda är inte ättlingar till root

(Det är det förväntade resultatet av att använda React Portal)

Som sådan, om du tillämpar dina CSS-regler på ett element inom root, kommer det inte att påverka stilen på ditt portal-innehåll, eftersom de inte är faktiska DOM-efterkommande av det elementet (även om du skapade dem i React från en barnkomponent).

I ditt fall kan du helt enkelt applicera din stil direkt på bakgrunden och modalen.

Det verkar som att du försökte med modal, men eftersom stilen tillämpas på samma element som har className .modal, matchar det inte din CSS som riktar sig mot en .modal inom elementet som får stilen.

Du skulle kunna göra till exempel:

export const ModalStyles = css`
      position: fixed;
      top: 30vh;
      left: 10%;
      width: 60%;
      height: 50%
      z-index: 100;
      overflow: hidden;
`;

const ModalOverlay = () => {
  return (
    <div css={ModalStyles}>
      {/* etc. */}
    </div>
  );
};