Home > Blockchain >  positioning a rotated 90deg element isn't responsive
positioning a rotated 90deg element isn't responsive

Time:07-24

I have this project, with this navbar enter image description here

like you see I am using flexbox, and it is correctly viewed.

but they tell me that I need that the navbar is rotated, and the text be viewed like so:

  • rotated 90deg.
  • hover working fine with the same rotation.
  • the black line at the bottom should be on the right side.

something like this (this is only photoshopped image for you, so you can understand):

enter image description here

and for you can seem easy but I know some CSS, and I know how to rotate it

by using:

   transform: rotate(90deg);

but here is the problem, isn't positioned correctly.

so before I will tell you the problems, I will put you my first code without rotating (so it will be easier to you to debug with the next following code)

:root {
  --height: 3rem;
  --triangle-width: 1rem;
  --bg: #ccc;
  --angle: 20deg;
  --text-color: black;
}

* {
  box-sizing: border-box;
}

nav {
  display: flex;
  gap: var(--triangle-width);
  color: var(--text-color);
  position: relative;
  margin: 0 var(--triangle-width);
}

nav::before {
  content: "";
  position: absolute;
  bottom: 0;
  background: var(--text-color);
  height: 0.2rem;
  width: 100%;
}

nav div {
  display: grid;
  place-items: center;
  height: var(--height);
  width: calc(100% - (var(--triangle-width) * 2));
  position: relative;
  text-transform: uppercase;
}

nav div:hover {
  background-color: var(--bg);
}

nav div:hover::before {
  content: "";
  position: absolute;
  top: 0;
  left: calc(-1 * (var(--triangle-width) / 2));
  height: var(--height);
  width: var(--triangle-width);
  background-color: var(--bg);
  transform: skewX(calc(-1 * var(--angle)));
}

nav div:hover::after {
  content: "";
  position: absolute;
  top: 0;
  right: calc(-1 * (var(--triangle-width) / 2));
  height: var(--height);
  width: var(--triangle-width);
  background-color: var(--bg);
  transform: skewX(var(--angle));
}

nav div::before,
nav div::after {
  z-index: -1;
}

nav::before {
  z-index: 1;
}
<nav>
  <div>instagram</div>
  <div>microsoft</div>
  <div>facebook</div>
  <div>linkedin</div>
  <div>youtube</div>
</nav>

the snippet you see up here is the normal flex navbar without rotating

list of problems

  • the half element is invisible, and seems to overflow

enter image description here

  • is not in its place, like I want (seems to be centered, but I want that it will be on the left side)

enter image description here

  • if I expand the height is not changing, but if I change the width is changing.

I want that if is rotated, the width of the nav is the height of the device.
so if the device is smaller remains the same as the viewport width is higher... but the difference happens only if the height changes.

here are some examples:

small width
enter image description here

bigger width
enter image description here

as you see there is some gaps that change a lot, I just want it will be responsive like the code without transform: rotate(90deg)



now that you know the problem, I will tell how I tried to solve it

I used this code: enter image description here

transform: translate(45vw, 45vw);

that seems to solve something, but only on 900px exactly width of the viewport

enter image description here

so I need to use a lot @media to make it work :(

here an example:

500px
the text is smaller, no gaps
enter image description here

300px
the black line of the border disappears completely, the text hasn't any gap between
enter image description here

1500px
the gaps are much bigger, the black line is moving to the right, most of the text isn't visible enter image description here


now another bug that I solved is using -90deg intead of 90deg to make the border to the right. enter image description here

so what I want?

  • a simple css solution,
  • that makes the nav responsive to the height of the device
  • with the same behavior of grid 1fr (but in my case I am using flex then rotate it)
  • the text need to be always visible inside the height of the device
  • don't change with the width, change only with the height
  • gaps don't get bigger a lot
  • border line need to be on the right

enter image description here

ok. now here my code:

:root {
  --height: 3rem;
  --triangle-width: 1rem;
  --bg: #ccc;
  --angle: 20deg;
  --text-color: black;
}

* {
  box-sizing: border-box;
}

nav {
  display: flex;
  gap: var(--triangle-width);
  color: var(--text-color);
  position: relative;
  margin: 0 var(--triangle-width);
  transform: rotate(-90deg) translate(-45vw, -45vw);
}

nav::before {
  content: "";
  position: absolute;
  bottom: 0;
  background: var(--text-color);
  height: 0.2rem;
  width: 100%;
}

nav div {
  display: grid;
  place-items: center;
  height: var(--height);
  width: calc(100% - (var(--triangle-width) * 2));
  position: relative;
  text-transform: uppercase;
}

nav div:hover {
  background-color: var(--bg);
}

nav div:hover::before {
  content: "";
  position: absolute;
  top: 0;
  left: calc(-1 * (var(--triangle-width) / 2));
  height: var(--height);
  width: var(--triangle-width);
  background-color: var(--bg);
  transform: skewX(calc(-1 * var(--angle)));
}

nav div:hover::after {
  content: "";
  position: absolute;
  top: 0;
  right: calc(-1 * (var(--triangle-width) / 2));
  height: var(--height);
  width: var(--triangle-width);
  background-color: var(--bg);
  transform: skewX(var(--angle));
}

nav div::before,
nav div::after {
  z-index: -1;
}

nav::before {
  z-index: 1;
}
<nav>
  <div>instagram</div>
  <div>microsoft</div>
  <div>facebook</div>
  <div>linkedin</div>
  <div>youtube</div>
</nav>

CodePudding user response:

I would simplify your code and only consider 4 properties to rotate and correctly set the height of your element. I also updated your HTML code for a better semantic markup

:root {
  --height: 3rem;
  --triangle-width: 1rem;
  --bg: #ccc;
  --text-color: black;
}
nav {
  display: flex;
  color: var(--text-color);
  border-bottom: 0.2rem solid var(--text-color); 
  position: absolute;
  min-width: fit-content;  /* in case we have small height */
  /* you need the below */
  inset: 0 auto auto var(--triangle-width);
  width: calc(100vh - 2*var(--triangle-width));
  transform-origin: 0 0;
  transform: rotate(-90deg) translate(calc(-100% - var(--triangle-width)));
  /**/
}
nav ul {
  display: flex;
  width: 100%;
  justify-content: space-around;
  gap: var(--triangle-width);
  margin: 0;
  padding: 0;
  list-style: none;
}
nav ul li {
  display: grid;
  place-items: center;
  min-height: var(--height);
  position: relative;
  z-index: 0;
  text-transform: uppercase;
  cursor: pointer;
}

nav ul li:before {
  content: "";
  position: absolute;
  z-index: -1;
  inset: 0 calc(-1*var(--triangle-width));
  clip-path: polygon(var(--triangle-width) 0, calc(100% - var(--triangle-width)) 0, 100% 100%, 0 100%);
}

nav ul li:hover:before {
  background: var(--bg);
}
<nav>
  <ul>
    <li>instagram</li>
    <li>microsoft</li>
    <li>facebook</li>
    <li>linkedin</li>
    <li>youtube</li>
  </ul>
</nav>

  • Related