Discussion on Positioning and other related positions issues

<div class="header-top">
  <picture class="picture">
    <img src="img/warrenbuffet.png" alt="">
  </picture>
</div>

The related CSS is →

.header-top {
  display: flex;
  margin: auto;
  margin-bottom: 40px;
  align-items: center;
}

picture.picture {
  border: 2px solid red;
  margin: auto;
}
.picture img {
  margin: auto;
  width: 80%;
  max-width: 200px;
  border-radius: 50%;
  border: 2px solid red;
}

Issue: The image is not aligned in the horizontal center.
Question →

.picture img {
  margin: auto;

margin auto is not working, why?
image

However:
display: flex; + margin: auto;
works?

image

The image is an inline element and margin:auto does not apply to inline elements . On its own you would need display:block on the image for auto margins to work.

When the image is a direct child of a flex parent (i.e. picture.picture has display:flex applied) then it becomes a flex item (it is no longer treated as an inline element) and the margin will then take effect.

3 Likes

Ok. display:flex also worked. with that said(your detailed explanation), when we apply any display CSS we withdraw default inline property on the img tag. I guess this is the explanatory validation.

1 Like

Yes if you make the image display:flex then it also works with auto margins as would display values of table, grid and others but only those that have a block basis. E.g inline- block will not work with auto margins.

Note also that position absolute elements will also obey auto margins in the right structure.

1 Like

I have created a codepen → https://codepen.io/codeispoetry/pen/QWvbPqP

It is working, but I have lot of confusions:

  1. In CSS my underatanding is that default position when approcahing is
    X axis follows this way → and
    Y axis follows this way ↓ (-ve Y axis as compared to mathematical cordinates)

Currently when we are not using any positioning(absolutee, relative, fixed, sticky) when we click it appears top and bottom linear blocks are rotating as if they are hinged in between and the rotation is from the center of those lines?

Rotate works off a center axis, so you’ll have to play with the transform origin

This isn’t quite right, but the scale throws the numbers off some, so you’ll have to play with it. (Added the color to make it easy to see which line was which when playing with it…)

body.clicked .top {
  background-color: green;
  transform: rotateZ(45deg) scaleX(1.25);
  transform-origin: 0% 100%;
}
body.clicked .bottom {
  background-color: red;
  transform: rotateZ(-45deg) scaleX(1.25);
  transform-origin: 45% -45%;
}
2 Likes

I was able to achive something through hit and trial before:

body.clicked .top {
  transform: rotateZ(45deg) scaleX(1.25) translate(13px, 13px);
}
body.clicked .bottom {
  transform: rotateZ(-45deg) scaleX(1.25) translate(7px, -7px);
}

But still, I was looking for a much better approach. can we simplify it through any positioning method?

I use a simpler approach here and I don’t worry about extending the line.

2 Likes

Hi there, You haven’t used JS, how come the class .open, which is initially not in the HTML is used and excercising its influence?

The demo was just a bare bones example of how the hamburger lines could be changed easily. You would need js to add the open class instead of using hover.

e.g. Like this.

1 Like

Hi there, I have a general question in this pseudo method: before and after is it a mandate that we have to position them absolute with parent real HTML property as a relative? Because I browsed various examples and found that a consistency?

No, not all.

It’s probably easiest to explain if you imagine before and after are behaving exactly like this html.

<div>
  <span class="before"> I'm the content 'before' the existing content in this div</span>
  
  I'm the content in this div.
  
   <span class="after"> I'm the content 'after' the existing content in this div</span>
</div>

When you add content using before and after it will render exactly like the html above. The content will be inserted before and after the content in that div and behave like inline content just like a span.

The reason position:absolute is used a lot (with a relative parent) is that a lot off times the elements are used for decoration and special effects which in the most case require them to be placed somewhere other than inline.

If you just think of before and after as empty spans in your div then you can style them exactly as you would do with those spans (the benefit being that you don’t need to add extra empty spans to your mark up).

2 Likes

Thanks for the clarification.

1 Like

In the example that you have shared, you are rotating the top and bottom border by 45/-45 degrees or before and after. I was trying to find out by commenting and uncommenting, the more I got confused?

If you change the transition speed to 5 seconds you can see the magic :slight_smile:

The top and bottom lines are the top and bottom borders of the button itself.

The middle line is two lines on top of each other to make one line (:before and :after).

When clicked one line is rotated 45deg and one is rotated -45deg. Because they are both in the exact same space they transition nicely without needing to translate or do anything fancy. The top and bottom lines are just hidden during the change.

1 Like

OK, Got the logic I will approach the code fresh now.

How did you come to the conclusion that it should be 6px from the top?

1/2 of 21 px is 10.5 px,

Or you took 3 heights:
Border-top+ border-bottom + height of pseudo containers(since they are overlapping because of absolute positioning so they will be counted once) = 3+3+3 =9

(21-9= 12)/2 = 6px

Or my arithematical understanding is just a coincidence, and have no association with the 6px chosen?

It’s just basic math. :slight_smile:

The element is 21px tall and has 3px top and bottom borders. That leaves 15px space in the middle.

The middle bar is 3px wide and has 6px space above and below it when placed at top 6px.

3 + 6 + 3 + 6 + 3 = 21

1 Like

This is a very intelligent design and a great learning for me.

1 Like

I have implemented the solution here

I have eliminated position:abolsute in many parts, but those [seduo elements which needs to coincide should have position absolute so I have retained there.

Final JS →

(function (evt) {
  const hamBurger = evt.querySelector(".whamburger");
  hamBurger.addEventListener("click", hamBurgerClick);
  function hamBurgerClick() {
	  const heyBody  = document.querySelector("body");	
	        heyBody.classList.toggle('clicked');
  }
})(document);

.top = .whamburger
.toggle = .wtoggle

I have completely eliminated → .open class with body.clicked (as you did it initially with another project)

body.clicked .wtoggle {
  border-color: transparent;
}
body.clicked .wtoggle:before {
  transform: rotate(45deg);
}
body.clicked .wtoggle:after {
  transform: rotate(-45deg);
}

Everything is wokring fine except on hamburger click suddenly vertical scroll bar disappears for fraction of a second and then appear that deiates a smooth transition or animation.