ARTLUNG LAB Share

Created Jun 2025

Popover à la Windows 95

HTML


<main>

    <button popovertarget="window-exe" popovertargetaction="show">
        In the manner of Windows 95, as one does.
    </button>

    <aside id="window-exe" popover>
        <section>
            <h2>window.exe</h2>
            <form>
                <label aria-label="Regular Size">
                    <input type="radio" name="state" value="normal" checked>
                    <span>Regular</span>
                </label>
                <label aria-label="Fullscreen">
                    <input type="radio" name="state" value="fullscreen">
                    <span>Fullscreen</span>
                </label>
                <button aria-label="Close" onclick="document.querySelector('#window-exe').hidePopover();return false;">Close</button>
            </form>
        </section>
        <div>
            <p>
                I don't necessarily feel nostalgic about
                Windows 95, but I do appreciate the aesthetic of the thing. I'm stunned that it's 30 years old.
            </p>
            <p>
                It's fun to replicate some of the features
                of the interface using current (2025) web techniques.
                The Popover API (<a href="https://developer.mozilla.org/en-US/docs/Web/API/Popover_API">MDN</a>) is worth a look.
            I don't believe I could articulate the number of times I created popovers of different sorts
            using HTML and JavaScript and "Dynamic HTML" and now we can have it with nearly zero JavaScript.

            <p>
            <p>
                I also like using Sass (<a href="https://sass-lang.com/">Sass</a>) to create stylesheets I can read logically. And playing with
                CSS gradients is one of my greatest joys.
            </p>

            <p>Thanks for reading,<br>
                <a href="https://artlung.com/">Joe (ArtLung)</a>
            </p>
        </div>

    </aside>
</main>

SCSS

[popovertarget="window-exe"][popovertargetaction="show"] {
  --size: 1.1;
  color: #000;
  border: none;
  box-sizing: border-box;
  height: 6.5lh;
  padding: 5lh 0 0 0;
  line-height: 1;
  font-size: calc(var(--size) * 1rem);
  text-wrap: nowrap;
  image-rendering: pixelated;
  justify-content: end;
  align-items: end;
  background: url("data:image/gif;base64,R0lGODlhIAAbAKIAAP//AMDAwP///wAAAICAgICAAP///wAAACH5BAUAAAYALAAAAAAgABsAAAN5aGrU7ivKGYm4GBPKpQUBKIbB1nEfOY7mWQVwLM9PXQ9Mpu88PwyplWooFBaAAqKyuDwGl1CmM8msRqfWrHIa7Rax3jCIqy2HwGYtWexFs63r9BUpVyPfbToefq/Pn35GfXtNeoFbQAWKi4yNjo+KOD+TlJWWl5MGCQA7")
  50% 0 / 5lh 5lh no-repeat;
  font-family: "-apple-system", BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
  Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  cursor: pointer;
  &::first-line {
    background: rgba(255,255,255,.5);
  }
}

#window-exe {
  --gradient-color-1: #02046a;
  --gradient-color-2: #2182bf;
  --title-color: #fff;
  --text-color: #282828;
  --window-color: #bfbfc1;
  max-width: 80ch;
  &:has(input[value="fullscreen"]:checked) {
    max-width: unset;
    width: 98vw;
    height: 98vh;
  }
  font-family: "-apple-system", BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
  Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
  font-size: 1rem;
  border: 2px solid;
  border-color: var(--title-color) var(--text-color) var(--text-color)
  var(--title-color);
  background: var(--window-color);
  > section {
    background: linear-gradient(
                    90deg,
                    var(--gradient-color-1),
                    var(--gradient-color-2)
    );
    display: flex;
    align-items: center;
    h2 {
      margin: 0;
      flex-grow: 1;
      padding: 0 0 0.1ch 0.5ch;
      color: var(--title-color);
    }
    form {
      font-size: 1rem;
      display: flex;
      gap: 0;
      > * {
        cursor: pointer;
        margin: 4px 2px;
        font-size: 1rem;
        border: 2px solid;
        border-color: var(--title-color) var(--text-color) var(--text-color)
        var(--title-color);
        display: flex;
        justify-content: center;
        align-items: center;
        background: var(--window-color);
        max-width: 3ch;
        color: #0000;
        overflow: hidden;
        &:has(input:checked) {
          cursor: not-allowed;
        }
        &:has(input[value="normal"]) {
          background: linear-gradient(
                          to top,
                          var(--text-color) 4px,
                          #0000 0
          ) 50% 50% / 2ch 2ch no-repeat var(--window-color);
        }
        &:has(input[value="fullscreen"]) {
          background: linear-gradient(
                          to top,
                          var(--text-color) 2px,
                          #0000 0
          ) 50% 50% / 2ch 2ch no-repeat,
          linear-gradient(
                          to bottom,
                          var(--text-color) 4px,
                          #0000 0
          ) 50% 50% / 2ch 2ch no-repeat,
          linear-gradient(
                          90deg,
                          var(--text-color) 2px,
                          #0000 0
          ) 50% 50% / 2ch 2ch no-repeat,
          linear-gradient(
                          -90deg,
                          var(--text-color) 2px,
                          #0000 0
          ) 50% 50% / 2ch 2ch no-repeat var(--window-color);
        }
        &:is(button) {
          background: linear-gradient(
                          45deg,
                          #0000 43%,
                          var(--text-color) 0 57%,
                          #0000 0
          )
          50% 50% / 2ch 2ch no-repeat,
          linear-gradient(-45deg,
                          #0000 43%,
                          var(--text-color) 0 57%,
                          #0000 0
          ) 50% 50% / 2ch 2ch no-repeat var(--window-color);
        }
      }
      input[type="radio"] {
        display: none;
      }
    }
  }
  div {
    padding: 0 1ch;
    color: var(--text-color);
    overflow: auto;
  }
}

main {
  background: #008080;
  width: 100%;
  height: 60vh;
  box-sizing: border-box;
  padding: 3lh;
}

CSS (compiled)

[popovertarget=window-exe][popovertargetaction=show]{--size: 1.1;color:#000;border:none;box-sizing:border-box;height:6.5lh;padding:5lh 0 0 0;line-height:1;font-size:calc(var(--size)*1rem);text-wrap:nowrap;image-rendering:pixelated;justify-content:end;align-items:end;background:url("data:image/gif;base64,R0lGODlhIAAbAKIAAP//AMDAwP///wAAAICAgICAAP///wAAACH5BAUAAAYALAAAAAAgABsAAAN5aGrU7ivKGYm4GBPKpQUBKIbB1nEfOY7mWQVwLM9PXQ9Mpu88PwyplWooFBaAAqKyuDwGl1CmM8msRqfWrHIa7Rax3jCIqy2HwGYtWexFs63r9BUpVyPfbToefq/Pn35GfXtNeoFbQAWKi4yNjo+KOD+TlJWWl5MGCQA7") 50% 0/5lh 5lh no-repeat;font-family:"-apple-system",BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";cursor:pointer}
[popovertarget=window-exe][popovertargetaction=show]::first-line{background:rgba(255,255,255,.5)}
#window-exe{--gradient-color-1: #02046a;--gradient-color-2: #2182bf;--title-color: #fff;--text-color: #282828;--window-color: #bfbfc1;max-width:80ch;font-family:"-apple-system",BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";font-size:1rem;border:2px solid;border-color:var(--title-color) var(--text-color) var(--text-color) var(--title-color);background:var(--window-color)}
#window-exe:has(input[value=fullscreen]:checked){max-width:unset;width:98vw;height:98vh}
#window-exe>section{background:linear-gradient(90deg, var(--gradient-color-1), var(--gradient-color-2));display:flex;align-items:center}
#window-exe>section h2{margin:0;flex-grow:1;padding:0 0 .1ch .5ch;color:var(--title-color)}
#window-exe>section form{font-size:1rem;display:flex;gap:0}
#window-exe>section form>*{cursor:pointer;margin:4px 2px;font-size:1rem;border:2px solid;border-color:var(--title-color) var(--text-color) var(--text-color) var(--title-color);display:flex;justify-content:center;align-items:center;background:var(--window-color);max-width:3ch;color:rgba(0,0,0,0);overflow:hidden}
#window-exe>section form>*:has(input:checked){cursor:not-allowed}
#window-exe>section form>*:has(input[value=normal]){background:linear-gradient(to top, var(--text-color) 4px, rgba(0, 0, 0, 0) 0) 50% 50%/2ch 2ch no-repeat var(--window-color)}
#window-exe>section form>*:has(input[value=fullscreen]){background:linear-gradient(to top, var(--text-color) 2px, rgba(0, 0, 0, 0) 0) 50% 50%/2ch 2ch no-repeat,linear-gradient(to bottom, var(--text-color) 4px, rgba(0, 0, 0, 0) 0) 50% 50%/2ch 2ch no-repeat,linear-gradient(90deg, var(--text-color) 2px, rgba(0, 0, 0, 0) 0) 50% 50%/2ch 2ch no-repeat,linear-gradient(-90deg, var(--text-color) 2px, rgba(0, 0, 0, 0) 0) 50% 50%/2ch 2ch no-repeat var(--window-color)}
#window-exe>section form>*:is(button){background:linear-gradient(45deg, rgba(0, 0, 0, 0) 43%, var(--text-color) 0 57%, rgba(0, 0, 0, 0) 0) 50% 50%/2ch 2ch no-repeat,linear-gradient(-45deg, rgba(0, 0, 0, 0) 43%, var(--text-color) 0 57%, rgba(0, 0, 0, 0) 0) 50% 50%/2ch 2ch no-repeat var(--window-color)}
#window-exe>section form input[type=radio]{display:none}
#window-exe div{padding:0 1ch;color:var(--text-color);overflow:auto}
main{background:teal;width:100%;height:60vh;box-sizing:border-box;padding:3lh}