Rotate Text and Shrink Its Container to the New Width

Rotate text and shrink its container to the new width

I found a workaround using absolute positioning. The rotated text can be absolutely positioned "relative to the border of its closest positioned ancestor". Explanation:

  • position: relative on container to make it the "closest positioned ancestor"
  • position: absolute on rotated text, set to bottom of container (minus line height)
  • rotate the text from the top-left corner

JSFiddle

.container {
position: relative; /*make container the closest positioned ancestor*/
border: 1px solid red;
display: inline-block;
height: 400px;
min-width: 30px; /*same as line-height of rotated text*/
}

.rotate {
text-align: center;
overflow: hidden;
height: 30px;
line-height: 30px;
width: 400px; /*matches the height of the container*/
position: absolute;
bottom: -32px; /*0 = bottom of container, then subtract (line-height+border)*/
border: 1px solid blue;
transform: rotate(-90deg);
transform-origin: top left;
}

Assumptions:

  • that text width can be set to a sensible value (e.g. height of container)
  • no line breaks in text (single-line solution)

Rotated elements in CSS that affect their parent's height correctly

Assuming that you want to rotate 90 degrees, this is possible, even for non-text elements - but like many interesting things in CSS, it requires a little cunning. My solution also technically invokes undefined behaviour according to the CSS 2 spec - so while I've tested and confirmed that it works in Chrome, Firefox, Safari, and Edge, I can't promise you that it won't break in a future browser release.

Short answer

Given HTML like this, where you want to rotate .element-to-rotate...

<div id="container">
<something class="element-to-rotate">bla bla bla</something>
</div>

... introduce two wrapper elements around the element that you want to rotate:

<div id="container">
<div class="rotation-wrapper-outer">
<div class="rotation-wrapper-inner">
<something class="element-to-rotate">bla bla bla</something>
</div>
</div>
</div>

... and then use the following CSS, to rotate anti-clockwise (or see the commented out transform for a way to change it into a clockwise rotation):

.rotation-wrapper-outer {
display: table;
}
.rotation-wrapper-inner {
padding: 50% 0;
height: 0;
}
.element-to-rotate {
display: block;
transform-origin: top left;
/* Note: for a CLOCKWISE rotation, use the commented-out
transform instead of this one. */
transform: rotate(-90deg) translate(-100%);
/* transform: rotate(90deg) translate(0, -100%); */
margin-top: -50%;

/* Not vital, but possibly a good idea if the element you're rotating contains
text and you want a single long vertical line of text and the pre-rotation
width of your element is small enough that the text wraps: */
white-space: nowrap;
}

Stack snippet demo

p {  /* Tweak the visuals of the paragraphs for easier visualiation: */  background: pink;  margin: 1px 0;  border: 1px solid black;}.rotation-wrapper-outer {  display: table;}.rotation-wrapper-inner {  padding: 50% 0;  height: 0;}.element-to-rotate {  display: block;  transform-origin: top left;  /* Note: for a CLOCKWISE rotation, use the commented-out     transform instead of this one. */  transform: rotate(-90deg) translate(-100%);  /* transform: rotate(90deg) translate(0, -100%); */  margin-top: -50%;
/* Not vital, but possibly a good idea if the element you're rotating contains text and you want a single long vertical line of text and the pre-rotation width of your element is small enough that the text wraps: */ white-space: nowrap;}
<div id="container">  <p>Some text</p>  <p>More text</p>  <div class="rotation-wrapper-outer">    <div class="rotation-wrapper-inner">      <p class="element-to-rotate">Some rotated text</p>    </div>      </div>  <p>Even more text</p>  <img src="https://i.stack.imgur.com/ih8Fj.png">  <div class="rotation-wrapper-outer">    <div class="rotation-wrapper-inner">      <img class="element-to-rotate" src="https://i.stack.imgur.com/ih8Fj.png">    </div>  </div>  <img src="https://i.stack.imgur.com/ih8Fj.png"></div>

Rotate the text inside td, but doesn't allow to increase the width of td?

Change this:

<td class="vertical-align">text</td>

Like this:

<td><span class="vertical-align">text</span></td>

I added span in td because I want to add writing-mode: vertical-rl style for text and td element does not support this properly. An example below:

table {  border-collapse:collapse}
table td { border:1px solid black}
.vertical-align { white-space:nowrap; -webkit-writing-mode: vertical-rl; -ms-writing-mode: tb-rl; writing-mode: vertical-rl; padding: 10%; /* optional */ transform: rotate(180deg) /* you want */}
<table width="100%">  <tr>    <td width="5%" rowspan="2"><span class="vertical-align">Dummy Heading Dummy Heading</span></td>    <td width="95%">Dummy Text Dummy Text</td>  </tr>  <tr>    <td width="95%">Dummy Text Dummy Text</td>  </tr></table>

CSS: adjusting spacing between letter according to container width?

...somewhere, in a javascript file far far away...

$(".container").each(function(idx, el) {
$(el).css("letter-spacing", calculateSpacing(el, $(el).height()));
});

You can use the plugin found here, which contains the calculateSpacing function, albeit it works on width, not height (so some modification may be necessary):

http://heychinaski.com/jquery/js/jquery.charjustify.js

svg text transform-rotate changes x and y position of text tag

You are rotating about the origin but the text is not at the origin. Imagine you have a clock where centre of the clock face is the origin and the minute hand is half past the hour ending at 0,175. 10 minutes ago the second hand was to the right and slightly above where it is now, same as your situation.

If you want to rotate about the start point of the text, translate it into position and then rotate it. That way the text is at the local origin when you rotate it.

<!DOCTYPE html><html><body>
<svg height="330" width="200"> <text fill="red" transform="translate(0, 175) rotate(-10.867784481465419)">I love SVG!</text> Sorry, your browser does not support inline SVG.</svg> </body></html>

How to NOT rotate text if the parent container is rotated

No html change:

a {    position: relative;    padding: 0;}a .main-link-text {    min-width: 100%;    position: absolute;    bottom: 0;    left: 0;    width: 100%;    height: 30%;    display: flex;    align-items: center;    justify-content: flex-start;    padding: 25px;    font-size: 2.5em;    text-decoration: underline;    font-weight: 700;    color: #fff;    z-index: 10;}a::after {    content: '';    position: absolute;    bottom: 0;    left: 0;    background: #c0392b;    transform: rotate(5DEG);    display: block;    width: 100%;    height: 60px;    z-index: 5;}img { width: 100% }
<a href="#">  <span>    <img src="https://www.safaribookings.com/blog/wp-content/uploads/2017/05/What-todo-Encounter-Elephant-BW_1200px.jpg" alt="image-rawpixel-761473-unsplash.png">  </span>  <span class="main-link-text">    Text to NOT rotate  </span></a>

How to make a dynamic text responsive to the container size

As mentioned in the comments, your problem here is that the text is wrapping because you gave its parent container a set width of 120px. If you A) ditch the width or B) give it a min-width of 120px, you will get it to resize to accommodate longer names.

.element {  display: inline-block;  background-color: #0074d9;  min-width: 120px;  margin-right: 5px;  margin-left: 5px;  padding: 0 10px;  animation: roll 3s infinite;  transform: rotate(30deg);  opacity: .5;}
@keyframes roll { 0% { transform: rotate(0); } 100% { transform: rotate(360deg); }}
<div class="element">  <p>Welcome!</p>  <p>Someguy Longlastname</p>  <p>${user_email}</p>  <p>${user_contact} </p></div>


Related Topics



Leave a reply



Submit