CSS rotate text by n degress, but not the boundary box?

半腔热情 提交于 2021-02-04 16:07:59

问题


I am aware of the CSS transform: rotate property, and the methods used to make an angled div element, but there is one very important design element that I cannot find addressed anywhere:

How to keep the boundary box angled

When I create angled div elements, I use a wrapper element that is rotated by n degrees, and then the child element (often a span) that's rotated -n degrees. Unfortunately, this causes the child element to have its own rectangular boundary independent of its parent element.

The below image is a very basic example of what everyone seems to be alright with, where the child element's text is inside an un-angled rectangle, but this is not what I want:

.parent {
    width: 200px;
    height: 200px;
    transform: rotate(30deg);
    background-color: blue; /* for clarity in img */
}
.child {
    display: inline-block;
    transform: rotate(-30deg);
    background-color: rgba(250, 80, 80, 0.4); /* for clarity in img */
}

It's worth noting that the child element must have display: inline-block in order to actually be rotated.

Here's approximately what I'm looking for:

                                  Some
                            text goes here
                       and automatically just-
                  ifies to the shape of the parent
              element which in this case hap-
         pens to be a rectangle. Here's
            more text to show the
                full shape..
                     --

I've tried using text-orientation, different position value combinations, and other tricks with transform, but I can't get the text to behave as though the parent element is its boundary; instead it just creates its own!

I'm alright with a JavaScript solution, but pure CSS would certainly be nice. Hopefully this is enough information for a qualified individual to solve the problem.

Thanks for your time!


回答1:


I think the only way to approximate this is to consider shape-outside but it would be very tricky to get the correct values.

Below an illustration. All you have to do is to update the width/height values to control the overall shape:

.container {
  display: flex;
  width: 400px;
  margin: 20px auto;
  text-align: justify;
}

.box>div {
  display: inline;
}

.box>div:before,
.box>div:after {
  content: "";
  float: left;
  shape-outside: linear-gradient(var(--d), #fff 49%, transparent 50%);
  background: linear-gradient(var(--d), transparent 49.5%, red 50% 51%, transparent 51.5%);
}

.box>div:after {
  float: right;
}

.box>div:first-child:before {
  --d: to bottom right;
  width: 60%;
  height: 120%;
}

.box>div:first-child:after {
  --d: to bottom left;
  width: 40%;
  height: 140%;
}

.box>div:last-child:before {
  --d: to top right;
  width: 40%;
  height: 140%;
}

.box>div:last-child:after {
  --d: to top left;
  width: 60%;
  height: 120%;
}
<div class="container">
  <div class="box">
    <div></div>
    <div></div>
    Lor em ipsum dolor sit amet, consectetur adipiscing elit. Sed id dolor nisl. Curabitur efficitur imperdiet dui quis molestie. Sed interdum elit ut sem pharetra lacinia. Proin porta auctor risus ac tempus. Etiam mollis malesuada diam at ultrices. Cras
    vel congue nisl, non auctor lorem. Nam ac lobortis nulla.
  </div>
</div>

We can add more CSS variables to make it more flexible:

.container {
  --w: 60%;
  --h1: 110%;
  --h2: 130%;
  display: inline-flex;
  width: 300px;
  margin: 20px auto 200px;
  text-align: justify;
}

.box>div {
  display: inline;
}

.box>div:before,
.box>div:after {
  content: "";
  float: left;
  shape-outside: linear-gradient(var(--d), #fff 49%, transparent 50%);
  background: linear-gradient(var(--d), transparent 49.5%, red 50% 51%, transparent 51.5%);
}

.box>div:after {
  float: right;
}

.box>div:first-child:before,
.box>div:last-child:after {
  --d: to bottom right;
  width: var(--w);
  height: var(--h1);
}

.box>div:first-child:after,
.box>div:last-child:before {
  --d: to bottom left;
  width: calc(100% - var(--w));
  height: var(--h2);
}

.box>div:last-child:before {
  --d: to top right;
}

.box>div:last-child:after {
  --d: to top left;
}
<div class="container">
  <div class="box">
    <div></div>
    <div></div>
    Lor em ipsum dolor sit amet, consectetur adipiscing elit. Sed id dolor nisl. Curabitur efficitur imperdiet dui quis molestie. Sed interdum elit ut sem pharetra lacinia. Proin porta auctor risus ac tempus. Etiam mollis malesuada diam at ultrices. Cras
    vel congue nisl, non auctor lorem. Nam ac lobortis nulla.
  </div>
</div>

<div class="container" style="--w:50%;--h1:120%;--h2:120%;">
  <div class="box">
    <div></div>
    <div></div>
    Lor em ipsum dolor sit amet, consectetur adipiscing elit. Sed id dolor nisl. Curabitur efficitur imperdiet dui quis molestie. Sed interdum elit ut sem pharetra lacinia. Proin porta auctor risus ac tempus. Etiam mollis malesuada diam at ultrices. Cras
    vel congue nisl, non auctor lorem. Nam ac lobortis nulla.
  </div>
</div>

<div class="container" style="--w:30%;--h1:120%;--h2:120%;">
  <div class="box">
    <div></div>
    <div></div>
    Lor em ipsum dolor sit amet, consectetur adipiscing elit. Sed id dolor nisl. Curabitur efficitur imperdiet dui quis molestie. Sed interdum elit ut sem pharetra lacinia. Proin porta auctor risus ac tempus. Etiam mollis malesuada diam at ultrices. Cras
    vel congue nisl, non auctor lorem. Nam ac lobortis nulla.
  </div>
</div>

Note that the values are closely related to the text you are using. You will need a lot of trial and error to get the best values (I doubt there is a generic solution that work with any content ...)

Related question: How to wrap text around a shape with border-radius?




回答2:


The only way I see that this may be achieved is a combinaison of skewx and words sequencing, see the snippet below.

#myDiv {
  transform: skewX(-50deg);
  width: 300px;
  height: 100px;
  background-color: yellow;
  border: 1px solid black;
  padding: 0px 10px;
}
#myDiv span {
  transform: skewX(50deg);
  display: inline-block;
}
<div id="myDiv">
<span>This</span> <span>amazing</span> <span>text</span> <span>will</span> <span>fit</span> <span>inside</span> <span>your</span> <span>container</span> <span>being</span> <span>inclined</span> <span>!</span>.
</div>

The words separation is necessary as each word has to be unskewed one by one, and not the whole child if any in one block.



来源:https://stackoverflow.com/questions/63274994/css-rotate-text-by-n-degress-but-not-the-boundary-box

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!