4

I'm trying to make 4 circles appear when the central circle is clicked, much like

enter image description here.

However, when I resize the viewport, the position of the divs change, as shown in the code below. I tried making the position relative, but that doesn't work. https://codepen.io/Refath/pen/NJbEQO

Here's the code in question:

.subOne{
    position: relative;
    top: -200px;
    left: 445px;
}

.subTwo{
    position: relative;
    top: -650px;
    left: 445px;
}

.subThree{
    position: relative;
    top: -570px;
    left: 255px;
}

.subFour{
    position: relative;
    top: -670px;
    left: 650px;
}

One idea I had was to wrap the subcircles in a seperate container div, and translate the container based on the viewport, although I'm not sure how feasible that would be.

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
DarkRunner
  • 449
  • 4
  • 15
  • What size is the original viewport where this should be working? At what size does it break down? What is the intended look of this design for a mobile viewport? Seems impossible to answer this question without that information. – serraosays Mar 06 '19 at 03:58

4 Answers4

1

With position: relative on the surrounding items and pixel positioning, you're not going to get a responsive layout.

First, with position: relative, the element is positioned relative to its original position, not the center circle. This results in a misalignment.

Second, a positioned element with top: -670px; left: 650px; may look okay on wider screens, but is way outside the viewport on smaller screens. This also messes up your alignment.

Instead, remove the surrounding items from the normal flow with position: absolute, make them relative to their container (with position: relative), and use percentage lengths for adaptability.

revised codepen

$(document).ready(function() {

  $(".subOne").hide();
  $(".subTwo").hide();
  $(".subThree").hide();
  $(".subFour").hide();


  $(".mainCircle").bind('click', function() {
    $(this).toggleClass('blue');
    $(".subOne").slideToggle('fast');
    $(".subTwo").slideToggle('fast');
    $(".subThree").slideToggle('fast');
    $(".subFour").slideToggle('fast');

  });

});
body {
  margin: 0;
}

.container {
  position: relative;
}

.subContainer {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
  background: coral;
}

.mainCircle,
.subOne,
.subTwo,
.subThree,
.subFour {
  border: 2px red solid;
  height: 100px;
  width: 100px;
  border-radius: 100px;
  background: blue;
  transition: 0.3s ease all;
}

.subOne {
  position: absolute;
  top: 20%;
  left: 50%;
  transform: translate(-50%, -50%); /* see link below for explanation */
}

.subTwo {
  position: absolute;
  bottom: 20%;
  left: 50%;
  transform: translate(-50%, 50%);
}

.subThree {
  position: absolute;
  top: 50%;
  left: 20%;
  transform: translate(-50%, -50%);
}

.subFour {
  position: absolute;
  top: 50%;
  right: 20%;
  transform: translate(50%, -50%);
}

.mainCircle:hover {
  background: lightblue;
  transition: 0.3s ease all;
}

.blue {
  border: 10px black solid;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="subContainer">
    <div class="mainCircle"></div>
  </div>
  <div class="subOne"></div>
  <div class="subTwo"></div>
  <div class="subThree"></div>
  <div class="subFour"></div>
</div>

More details: Element will not stay centered, especially when re-sizing screen

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
1

You can use percentages instead of pixels to get the layout. But I would do this with a slight change in markup and using a wrapping flexbox like so:

  1. Move your circles into pseudo element and their hover styles.

  2. Put one circle in the first row, three in the second (including the mainCircle) and one in the last row - use order property for the ordering and and flex-basis for the number of circles in each row.

  3. You can use margin: 0 auto to center each circle in their space. And also throw in align-content: space-around for a uniform alignment.

  4. Now all you can adjust the relative distances by varying the height and width of the subContainer.

See demo below:

$(document).ready(function() {
  $(".subOne").hide();
  $(".subTwo").hide();
  $(".subThree").hide();
  $(".subFour").hide();
  $(".mainCircle").bind('click', function() {
    $(this).toggleClass('blue');
    $(".subOne").slideToggle('fast');
    $(".subTwo").slideToggle('fast');
    $(".subThree").slideToggle('fast');
    $(".subFour").slideToggle('fast');
  });
});
body {
  overflow-y: none;
}

.container {
  background: coral
}

.subContainer {
  display: flex;
  align-items: center;
  justify-content: center;
  align-content: space-around;
  flex-wrap: wrap;
  height: 97vh;
  height: 500px; /* ADJUST THIS */
  width: 500px;  /* ADJUST THIS */
  margin: 0 auto;
  background: coral;
}

.mainCircle,
.subOne,
.subTwo,
.subThree,
.subFour {
  flex: 0 0 auto;
}

.mainCircle:after,
.subOne:after,
.subTwo:after,
.subThree:after,
.subFour:after {
  content: '';
  display: block;
  border: 2px red solid;
  height: 100px;
  width: 100px;
  margin: 0 auto;
  border-radius: 100px;
  background: blue;
  transition: 0.3s ease all;
}

.mainCircle:hover:after {
  background: lightblue;
  transition: 0.3s ease all;
}

.blue:after {
  border: 10px black solid;
}

.subOne {
  order: 1;
  flex-basis: 100%;
}

.subTwo {
  order: 2;
  flex-basis: 33.33%;
}

.mainCircle {
  order: 3;
  flex-basis: 33.33%;
}

.subThree {
  order: 4;
  flex-basis: 33.33%;
}

.subFour {
  order: 5;
  flex-basis: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="subContainer">
    <div class="mainCircle"></div>
    <div class="subOne"></div>
    <div class="subTwo"></div>
    <div class="subThree"></div>
    <div class="subFour"></div>
  </div>
</div>
kukkuz
  • 41,512
  • 6
  • 59
  • 95
0

It can be done in a rather simple way using grid layout.

width: 100vw and height: 100vh ensure the container fills the screen.

display: grid, grid-template-rows: 1fr 1fr 1fr and grid-template-columns: 1fr 1fr 1fr split the available space into 3 rows / columns of equal height / width.

align-items: center and justify-items: stretch on the container and margin: auto on the child elements center the content of each cell horizontally and vertically.

Grid areas are for convenience.

.container {
    background: coral;
    width: 100vw;
    height: 100vh;
    display: grid;
    grid-template-rows: 1fr 1fr 1fr;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-areas:
        "TL TC TR"
        "ML MC MR"
        "BL BC BR";
    align-items: center;
    justify-items: stretch;
}

.subContainer{
    grid-area: MC;
    margin: auto;
}

.subOne{
    grid-area: TC;
    margin: auto;
}

.subTwo{
    grid-area: MR;
    margin: auto;
}

.subThree{
    grid-area: BC;
    margin: auto;
}

.subFour{
    grid-area: ML;
    margin: auto;
}

/* the rest is taken from the original CSS */

.mainCircle, .subOne, .subTwo, .subThree, .subFour{
    border: 2px red solid;
    height: 100px;
    width: 100px;
    border-radius: 100px;
    background: blue;
    transition: 0.3s ease all;
}

.mainCircle:hover{
    background: lightblue;
    transition: 0.3s ease all;
}

.blue{
    border: 10px black solid;
}
kukuruznik
  • 88
  • 6
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – ethry Oct 06 '22 at 20:11
0

You can try it with transform: translate(). I would also make the middle circle as a ::before and add other circles as children.

<div class = "container">
    <div class = "subContainer">
        <div class = "mainCircle">
        <div class = "subOne"></div>
        <div class = "subTwo"></div>
        <div class = "subThree"></div>
        <div class = "subFour"></div>
    </div>
</div>
body{
    overflow-y:none;
}

.subContainer{
    display: flex;
  align-items: center;
  justify-content: center;
  height: 97vh;
    background: coral;
}
.mainCircle:before {
    content: "";
    position: absolute;
} 
.mainCircle, .subOne, .subTwo, .subThree, .subFour{
    border: 2px red solid;
    height: 100px;
    width: 100px;
    border-radius: 100px;
    background: blue;
    transition: 0.3s ease all;
}

.mainCircle:hover{
    background: lightblue;
    transition: 0.3s ease all;
}

.blue{
    border: 10px black solid;
}

.subOne{
    transform: translate(-100%, -100%);
}

.subTwo{
    transform: translate(100%, -200%);
}

.subThree{
    transform: translate(-100%, -100%);
}

.subFour{
    transform: translate(100%, -200%);
}
dudule
  • 116
  • 5