skip to Main Content

I have created a basic star topology diagram using simple CSS and HTML. I have 2 problems with the code I have:

  1. When I try to add text to the bubbles, it overflows from the bubble and the text is not oriented based on the bubble.
  2. Instead of a simple bubble I would like a cloud shape.

Any suggestions/solutions would be highly appreciated.

* {
  margin: 0;
  padding: 0;
}

html,
body {
  height: 100%;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
}

figure {
  --containerWidth: 500px;
  --containerHeight: 500px;
  width: var(--containerWidth);
  height: var(--containerHeight);
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

figure div {
  background: gray;
  width: 140px;
  height: 140px;
  border-radius: 50%;
}

figure .connected-device {
  --connectedDeviceWidth: 100px;
  --connectedDeviceHeight: 100px;
  width: var(--connectedDeviceWidth);
  height: var(--connectedDeviceHeight);
  position: absolute;
  background: gold;
  top: 0;
  transform-origin: calc(var(--connectedDeviceHeight) / 2) calc(var(--containerHeight) / 2);
  display: flex;
  justify-content: center;
}

figure .connected-device::before {
  content: '';
  height: calc((var(--containerHeight) / 2) - var(--connectedDeviceHeight));
  display: block;
  border-right: 2px dashed grey;
  position: relative;
  top: var(--connectedDeviceHeight);
}

figure .connected-device:nth-of-type(2) {
  transform: rotate(calc(1 / var(--number-connectedDevices) * 360deg));
}

figure .connected-device:nth-of-type(3) {
  transform: rotate(calc(2 / var(--number-connectedDevices) * 360deg));
}

figure .connected-device:nth-of-type(4) {
  transform: rotate(calc(3 / var(--number-connectedDevices) * 360deg));
}

figure .connected-device:nth-of-type(5) {
  transform: rotate(calc(4 / var(--number-connectedDevices) * 360deg));
}

figure .connected-device:nth-of-type(6) {
  transform: rotate(calc(5 / var(--number-connectedDevices) * 360deg));
}

figure .connected-device:nth-of-type(7) {
  transform: rotate(calc(6 / var(--number-connectedDevices) * 360deg));
}

figure .connected-device:nth-of-type(8) {
  transform: rotate(calc(7 / var(--number-connectedDevices) * 360deg));
}
<figure style="--number-connectedDevices: 8">
  <div class="central-device"></div>
  <div class="connected-device"></div>
  <div class="connected-device"></div>
  <div class="connected-device"></div>
  <div class="connected-device"></div>
  <div class="connected-device"></div>
  <div class="connected-device"></div>
  <div class="connected-device"></div>
  <div class="connected-device"></div>
</figure>

2

Answers


  1. Here is my attempt.

    If each .connected-device had a sub-container, then I could rotate that in the opposite direction, but since that’s not the HTML given, instead I’ve used rotation for the stalks/lines/::before and translate for each .connected-device.

    Not everything is calculated and that is because to work out the translations nicely, I would have to use trigonometric functions such as sin and these are relatively new and so could cause some issues with browser compatibility.

    * {
      margin: 0;
      padding: 0;
    }
    
    html, body {
      height: 100%;
    }
    
    body {
      display: flex;
      align-items: center;
      justify-content: center;
    }
    
    figure {
      --containerWidth: 500px;
      --containerHeight: 500px;
      width: var(--containerWidth);
      height: var(--containerHeight);
      display: flex;
      justify-content: center;
      align-items: center;
      position: relative;
    }
    
    figure div {
      background: gray;
      width: 140px;
      height: 140px;
      border-radius: 50%;
    }
    
    figure .connected-device {
      --connectedDeviceWidth: 100px;
      --connectedDeviceHeight: 100px;
      --connectedStalkLength: 100px;
      width: var(--connectedDeviceWidth);
      height: var(--connectedDeviceHeight);
      position: absolute;
      background: gold;
      display: flex;
      align-items: center;
      justify-content: center;
      transform: translate(var(--translateX), var(--translateY));
    }
    
    figure .connected-device::before {
      content: '';
      height: var(--connectedStalkLength);
      display: block;
      border-right: 2px dashed grey;
      position: absolute;
      top: calc(var(--connectedDeviceHeight) / 2);
      transform-origin: top;
      transform:
          rotate(calc(var(--device-number) * 45deg))
          translate(0, calc(var(--connectedDeviceHeight) / 2));
    }
    
    figure .connected-device {
      --device-number: 1;
      --translateX: 150px;
      --translateY: -150px;
    }
    figure .connected-device:nth-of-type(2) {
      --device-number: 2;
      --translateX: 150px;
      --translateY: 0;
    }
    figure .connected-device:nth-of-type(3)  {
      --device-number: 3;
      --translateX: 150px;
      --translateY: 150px;
    }
    figure .connected-device:nth-of-type(4)  {
      --device-number: 4;
      --translateX: 0;
      --translateY: 200px;
    }
    figure .connected-device:nth-of-type(5)  {
      --device-number: 5;
      --translateX: -150px;
      --translateY: 150px;
    }
    figure .connected-device:nth-of-type(6)  {
      --device-number: 6;
      --translateX: -200px;
      --translateY: 0;
    }
    figure .connected-device:nth-of-type(7)  {
      --device-number: 7;
      --translateX: -200px;
      --translateY: -200px;
      --connectedStalkLength: 200px;
    }
    figure .connected-device:nth-of-type(8)  {
      --device-number: 8;
      --translateX: 0;
      --translateY: -200px;
    }
      <figure style="--number-connectedDevices: 8">
        <div class="central-device"></div>
        <div class="connected-device">hello all</div>
        <div class="connected-device">hello </div>
        <div class="connected-device">hello</div>
        <div class="connected-device">hello</div>
        <div class="connected-device">hello</div>
        <div class="connected-device">hello</div>
        <div class="connected-device">hello</div>
        <div class="connected-device">hello<br>all</div>
      </figure>
    Login or Signup to reply.
  2. The code in the question is not responsive so this snippet alters things slightly by setting CSS variables – the width of the whole and of the bubbles being calculated. The maximum width is set at 500px as in the question but on narrower viewports this will become the width of the viewport (100vw).

    Added text needs to be inside its own element so that it can be rotated back to be horizontal.

    The rotation setting is put in just once – using the position of the element –n to calculate the actual degrees.

    Just for demo the cloud is added as a background png image (this one is allowed for personal use only) but you may like to look into using a base64 image so you don’t need a separate file, and the image will be more responsive to different viewport sizes. It is added on a pseudo element so that it too can be rotated back to a horizontal position.

    <style>
      {
        margin: 0;
        padding: 0;
      }
      
      html,
      body {
        height: 100%;
      }
      
      body {
        display: flex;
        align-items: center;
        justify-content: center;
      }
      
      figure {
        --containerWidth: min(500px, 90vw);
        --containerHeight: var(--containerWidth);
        width: var(--containerWidth);
        height: var(--containerHeight);
        display: flex;
        justify-content: center;
        align-items: center;
        position: relative;
      }
      
      figure>div {
        background: gray;
        width: calc(var(--containerWidth) * 140 / 500);
        aspect-ratio: 1;
        border-radius: 50%;
      }
      
      figure .connected-device {
        --connectedDeviceWidth: calc(100 / 500 * var(--containerWidth));
        --connectedDeviceHeight: var(--connectedDeviceWidth);
        width: var(--connectedDeviceWidth);
        height: var(--connectedDeviceHeight);
        position: absolute;
        background: transparent;
        top: 0;
        transform-origin: calc(var(--connectedDeviceHeight) / 2) calc(var(--containerHeight) / 2);
        display: flex;
        justify-content: center;
        align-items: center;
        border-radius: 0;
      }
      
      figure .connected-device>div {
        position: absolute;
        z-index: 1;
      }
      
      figure .connected-device::after {
        content: '';
        background-image: url(https://i.stack.imgur.com/zCQAK.png);
        background-size: contain;
        background-position: center center;
        background-repeat: no-repeat;
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        z-index: -2;
        transform: rotate(calc((var(--n) - 1) / var(--number-connectedDevices) * -360deg));
      }
      
      figure .connected-device::before {
        content: '';
        height: calc((var(--containerHeight) / 2) - var(--connectedDeviceHeight));
        display: block;
        border-right: 2px dashed grey;
        position: absolute;
        /* note change */
        top: var(--connectedDeviceHeight);
      }
      
      figure .connected-device:nth-of-type(n) {
        transform: rotate(calc((var(--n) - 1) / var(--number-connectedDevices) * 360deg));
      }
      /* rotate the inner text back */
      
      figure .connected-device:nth-of-type(n)>div {
        transform: rotate(calc((var(--n) - 1) / var(--number-connectedDevices) * -360deg));
      }
      
      figure .connected-device:nth-of-type(2) {
        --n: 2;
      }
      
      figure .connected-device:nth-of-type(3) {
        --n: 3;
      }
      
      figure .connected-device:nth-of-type(4) {
        --n: 4;
      }
      
      figure .connected-device:nth-of-type(5) {
        --n: 5;
      }
      
      figure .connected-device:nth-of-type(6) {
        --n: 6;
      }
      
      figure .connected-device:nth-of-type(7) {
        --n: 7;
      }
      
      figure .connected-device:nth-of-type(8) {
        --n: 8;
      }
      
      figure .connected-device:nth-of-type(9) {
        --n: 9;
      }
    </style>
    <figure style="--number-connectedDevices: 8">
      <div class="central-device"></div>
      <div class="connected-device">
        <div>1</div>
      </div>
      <div class="connected-device">
        <div>2</div>
      </div>
      <div class="connected-device">
        <div>3</div>
      </div>
      <div class="connected-device">
        <div>4</div>
      </div>
      <div class="connected-device">
        <div>5</div>
      </div>
      <div class="connected-device">
        <div>6</div>
      </div>
      <div class="connected-device">
        <div>7</div>
      </div>
      <div class="connected-device">
        <div>8</div>
      </div>
    </figure>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search