I'm facing the following issue with my angled top and bottom div. It should be something like on the picture which I'm providing here. I want to use before pseudo element for the top part of the div and after for the bottom part of the div and the bottom is kinda working but I have only problem with the top.
Any ideas how I can accomplish that effect using my code?
I want it to look like this:
Here's what I have so far:
.example {
width: 100%;
height: 700px;
position: relative;
background: red;
}
.example:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
z-index: -1;
bottom: 0;
transform-origin: left bottom;
transform: skewY(-10deg);
}
.example:before {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
z-index: -1;
top: 0;
transform-origin: top left;
transform: skewY(5deg);
}
<div class="example">
<h1>SOME CONTENT</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit eius excepturi at voluptates, est enim amet. Architecto eaque est assumenda, placeat ipsam repellendus atque nihil dolores, eos, commodi, provident sunt. Lorem ipsum dolor sit amet, consectetur
adipisicing elit. In dicta ut corrupti beatae maiores, officiis saepe omnis voluptatem facilis eveniet ex voluptate, ipsam libero! Recusandae ipsam, provident quam enim rem!</p>
<h2>More Content</h2>
</div>
View on JSFiddle
The issue you are having is due to the position:absolute setting of the pseudo-elements (before/after). When you set the position to absolute the element no longer has any container boundaries to conform to and is positioned based on the html body left,right,top and bottom values.
Now your main container example div's position starts from the top and your after pseudo element needs to be a bit above it to show the angled background but as the pseudo element is not a block element to actually move the main div down due to it's position:absolute setting. You need to add top margin to move the main div down so that the pseudo element set above it is shown.
Here is another way of doing it using css border properties instead of css3 transform property.
https://codepen.io/Nasir_T/pen/GNKLNQ
Hope this explains you the reason of using margins to adjust absolute positioned pseudo-elements.
I added a 150px of margin to the top of you div
EDIT I also changed the skew degree to -5% and 5% rather than +-10%
.example {
width: 100%;
h height: 700px;
position: relative;
background: red;
margin-top: 150px;
}
.example:after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
z-index: -1;
bottom: 0;
transform-origin: left bottom;
transform: skewY(-5deg);
}
.example:before {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
z-index: -1;
top: 0;
transform-origin: top left;
transform: skewY(5deg);
}
I think it'd be easiest to skew white divs in :before and :after and then use z-index to bring your content to the front like so. Also added a margin-top to h1 which can be adjusted as needed.
.example {
width: 100%;
height: 700px;
position: relative;
background: red;
overflow: hidden;
}
.example:after {
content: "";
width: 110%;
height: 25%;
top: 0;
position: absolute;
background: white;
z-index: 1;
transform-origin: left bottom;
transform: skewY(-5deg);
}
.example:before {
content: "";
width: 110%;
height: 25%;
bottom: 0;
position: absolute;
background: white;
z-index: 1;
transform-origin: left bottom;
transform: skewY(5deg);
}
.example h1, .example p {
position: relative;
z-index: 5;
}
.example h1 {
margin-top: 205px;
}
<div class="example">
<h1>SOME CONTENT</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit eius excepturi at voluptates, est enim amet. Architecto eaque est assumenda, placeat ipsam repellendus atque nihil dolores, eos, commodi, provident sunt. Lorem ipsum dolor sit amet, consectetur adipisicing elit. In dicta ut corrupti beatae maiores, officiis saepe omnis voluptatem facilis eveniet ex voluptate, ipsam libero! Recusandae ipsam, provident quam enim rem!</p>
<h2>More Content</h2>
</div>
IF there's a static width, the effect is a LOT easier to create & control using borders:
.example {
width: 500px;
height: 700px;
position: relative;
background: red;
padding:100px 0px;
}
.example:after,
.example:before {
content:'';
position:absolute;
border-right:solid 500px transparent;
}
.example:before {
top:0px;
border-top:solid 100px #FFF;
}
.example:after {
bottom:0px;
border-bottom:solid 100px #FFF;
}
<div class="example">
<h1>SOME CONTENT</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Fugit eius excepturi at voluptates, est enim amet. Architecto eaque est assumenda, placeat ipsam repellendus atque nihil dolores, eos, commodi, provident sunt. Lorem ipsum dolor sit amet, consectetur
adipisicing elit. In dicta ut corrupti beatae maiores, officiis saepe omnis voluptatem facilis eveniet ex voluptate, ipsam libero! Recusandae ipsam, provident quam enim rem!</p>
<h2>More Content</h2>
</div>
Related
I want to make a modal with a image and other elements to the right, something like this:
I tried making the modal content as a grid with two columns, the problems is when I try to adjust the image to fill all the avaiable space in the modal content, it overflows like this:
My css code looks like this:
<div class="modal">
<div class="content">
<div class="frame">
<img src="https://picsum.photos/400" alt="Example">
</div>
<div class="text">
Lorem ipsum, dolor sit amet consectetur adipisicing elit. Quis est mollitia possimus omnis nisi quo
aliquid ad accusantium dignissimos corrupti. Impedit, asperiores magnam corporis iste possimus tempore
quisquam provident dicta. Lorem ipsum dolor sit, amet consectetur adipisicing elit. Quibusdam
consequuntur, incidunt hic dolorum tempora inventore id sint ullam magnam veniam eveniet vitae, harum
dolorem tenetur libero voluptate voluptatibus. Inventore, excepturi!
</div>
</div>
</div>
.modal {
position: fixed;
height: 100%;
width: 100%;
background-color: rgba($color: #000000, $alpha: 0.6);
display: grid;
place-items: center;
}
.content {
background-color: $color-white;
width: 60%;
height: 600px;
border-radius: 5px;
display: grid;
grid-template-columns: auto 300px;
}
.frame > img {
width: 100%;
max-height: 100%;
object-fit: cover;
}
.text {
padding: 2rem 1rem;
}
The modal I tried to do has the problem of the image overflow. I setted the container div to grid with two columns, but the image column overflows the container as we can see in the picture. I want the image to take the space avaiable in the container but maintaining the 1 : 1 aspect ratio, also to be responsive, when the user change the screen size the image always has to maintain the 1:1 aspect ratio and not crop the image.I setted the height as static pixels because I want to add a element with a scrolling bar that otherwise will overflow or expand the container if its height was declared as percentages.
Just specify a max-height to the container(.frame) it will start working fine for 1:1 images because max-height:100% doesn't mean anything if you don't specify a height for its parent
and if you want to work for any ratio then remove the width property from the .frame > img because if you don't specify a width it will adjust itself according to it's height
I think the easiest way would be to use css aspect-ratio like this:
img {
width: 100%;
aspect-ratio: 1;
}
you can read more about it here
I think the problem might be the fact that your image's parent ( .frame ) does not have a set height.Try adding this:
.frame {
height:100%
}
I solved it removing the height of the modal content div. This allow the image to take all the space it needs. For the text to the right to not overgrow the image, what i did was make a div container and inside it a p tag with position absolute and with the widht and height of his parent, but with overflow: scroll. This allowed me to have mi image in 1:1 ratio taking all the space it needs in the card but without the text overflowing things. Here is how I did it.
.modal {
position: fixed;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
display: grid;
place-items: center;
}
.container {
width: 60%;
display: grid;
grid-template-columns: 1fr 30%;
background-color: #f4f4ed;
}
.frame {
width: 100%;
height: 100%;
}
.frame img {
width: 100%;
height: 100%;
object-fit: cover;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
padding: 2em 0.8em;
}
.content h5 {
font-size: 1.4rem;
font-weight: 600;
color: #00f0b5;
}
.text {
flex-grow: 1;
position: relative;
height: 100%;
width: 100%;
overflow-y: scroll;
}
.text p {
font-size: 0.8rem;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.actions {
width: 100%;
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 0.5rem;
}
.actions button {
font-family: "Roboto Condensed", sans-serif;
font-weight: 600;
text-transform: uppercase;
border: none;
outline: none;
background-color: #00f0b5;
padding: 0.2em 0;
cursor: pointer;
font-size: 0.5rem;
}
body {
font-size: 62.5%;
box-sizing: border-box;
}
h5{
margin: 0;
line-height: 1;
}
<div class="modal">
<div class="container">
<div class="frame">
<img src="https://picsum.photos/800" alt="Some lorem picsum">
</div>
<div class="content">
<h5>Title</h5>
<div class="text">
<p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Laborum placeat sed voluptatem optio esse facere accusamus tempore, provident dolorem nemo rerum sit accusantium labore quae eveniet ea aliquam. Ipsa, aliquam? Lorem ipsum dolor sit amet consectetur,
adipisicing elit. Laborum placeat sed voluptatem optio esse facere accusamus tempore, provident dolorem nemo rerum sit accusantium labore quae eveniet ea aliquam. Ipsa, aliquam? Lorem ipsum dolor sit amet consectetur, adipisicing elit. Laborum
placeat sed voluptatem optio esse facere accusamus tempore, provident dolorem nemo rerum sit accusantium labore quae eveniet ea aliquam. Ipsa, aliquam?
</p>
</div>
<div class="actions">
<button>Accept</button>
<button>Cancel</button>
</div>
</div>
</div>
</div>
#keyframes mgm {
from {
max-height: 250px;
}
to {
max-height: 0px;
}
}
.mgm {
width: 180px;
border: 1px solid black;
padding: 10px;
animation: mgm 1s ease-in-out;
max-height: 250px;
overflow:hidden;
}
<div class="mgm">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae,
blanditiis qui porro possimus commodi laudantium voluptatum accusantium.
Maxime alias dolorum quo aliquam delectus qui illo officiis, consequuntur
asperiores fugiat ducimus!
</div>
By running above code, height of the content is decreasing from bottom only and animation stops at the top. But I want to decrease the height from both bottom and top equally i.e; animation should stop at the centre of the content.
How to achieve this ?
Alternate approach -
Yes we can do this by using scaleY CSS property but it shrinks the internal content. As given below -
#keyframes mgm {
from {
transform:scaleY(1);
}
to {
transform:scaleY(0);
}
}
.mgm {
width: 180px;
border: 1px solid black;
padding: 10px;
animation: mgm 1s ease-in-out;
max-height: 250px;
overflow:hidden;
}
<div class="mgm">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae,
blanditiis qui porro possimus commodi laudantium voluptatum accusantium.
Maxime alias dolorum quo aliquam delectus qui illo officiis, consequuntur
asperiores fugiat ducimus!
</div>
#dommmm's Answer is also correct. In case if you don't want to play with positioning you can achieve it with flex as well. This also has same approach of wrapping the animated div in a container.
Here the height is fixed to 250px (same as the max height of the animated div) to avoid page scrolling. And then the animated div is positioned to center.
I've also reduced padding top and bottom from 10px to 0px to achieve the div closing completely.
.animation-container {
display: flex;
align-items: center;
height: 250px;
}
#keyframes mgm {
from {
max-height: 250px;
padding: 10px 10px;
}
to {
max-height: 0px;
padding: 0px 10px;
}
}
.animation-container {
display: flex;
align-items: center;
height: 250px;
}
.mgm {
width: 180px;
border: 1px solid black;
padding: 10px;
animation: mgm 1s ease-in-out alternate infinite;
max-height: 250px;
overflow: hidden;
display: flex;
align-items: center;
}
<div class="animation-container">
<div class="mgm">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, blanditiis qui porro possimus commodi laudantium voluptatum accusantium. Maxime alias dolorum quo aliquam delectus qui illo officiis, consequuntur asperiores fugiat ducimus!
</div>
</div>
Another idea using clip-path where you don't need to deal with height
#keyframes mgm {
to {
clip-path: inset(50% 0);
}
}
.mgm {
width: 180px;
border: 1px solid black;
padding: 10px;
animation: mgm 1s ease-in-out infinite alternate;
clip-path: inset(0 0);
}
<div class="mgm">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, blanditiis qui porro possimus commodi laudantium voluptatum accusantium. Maxime alias dolorum quo aliquam delectus qui illo officiis, consequuntur asperiores fugiat ducimus!
</div>
To get the border effect, you can consider a pseudo element like below:
.mgm {
width: 180px;
padding: 10px;
animation: mgm 1s linear infinite alternate;
clip-path: inset(0 0);
position: relative;
}
#keyframes mgm {
to {
clip-path: inset(50% 0);
}
}
.mgm:before {
content: "";
position: absolute;
border: 1px solid black;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 1px 0;
animation: inherit;
animation-name: mgm-b;
}
#keyframes mgm-b {
to {
margin: 50% 0;
}
}
<div class="mgm">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, blanditiis qui porro possimus commodi laudantium voluptatum accusantium. Maxime alias dolorum quo aliquam delectus qui illo officiis, consequuntur asperiores fugiat ducimus!
</div>
The pseudo element can be enough if you don't want transparency:
.mgm {
width: 180px;
padding: 10px;
position: relative;
overflow:hidden;
}
.mgm:before {
content: "";
position: absolute;
border: 1px solid black;
box-shadow:0 0 0 200vmax #fff;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: 1px 0;
animation: mgm 1s linear infinite alternate;
}
#keyframes mgm {
to {
margin: 50% 0;
}
}
<div class="mgm">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae, blanditiis qui porro possimus commodi laudantium voluptatum accusantium. Maxime alias dolorum quo aliquam delectus qui illo officiis, consequuntur asperiores fugiat ducimus!
</div>
To achieve this effect you will need to place the text in a child container and position it absolutely. Shrinking the parent div in this manner will not shrink the internal content.
#keyframes mgm {
from {
transform: translateY(0%);
height: 150px; /* original container height */
}
to {
transform: translateY(75px); /* 50% of original container height */
height: 0px;
}
}
.mgm {
width: 50%;
border: 1px solid black;
animation: mgm 1s ease-in-out;
height: 150px;
overflow: hidden;
position: relative;
}
.mgm p {
position: absolute;
margin: 10px;
top: 50%;
transform: translateY(-50%);
max-height: 150px;
max-width: 100%;
}
<div class="mgm">
<p>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Recusandae,
blanditiis qui porro possimus commodi laudantium voluptatum accusantium.
Maxime alias dolorum quo aliquam delectus qui illo officiis, consequuntur
asperiores fugiat ducimus!
</p>
</div>
We are using Markdown (Kramdown) to generate a static website. For infoboxes, we can annotade paragraphs and get the following results:
{:.note .icon-check title="This is a title"}
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
And this is the converted HTML:
<p class="note icon-check" title="This is a title">
Lorem, ipsum dolor sit amet consectetur adipisicing elit.
</p>
The style is (SCSS):
p.note {
&::before {
float: right;
}
position: relative;
&[title]::after {
content: attr(title);
position: relative;
top: 0;
left: 0;
}
}
.icon::before {
content: "#";
}
As we are using Icomoon icon fonts, where the content is set in :before, the title must be in :after.
we won't change the Iconfont, so the icon must stay in :before
no additional distracting markup in the markdown, so no HTML wrapper
no Javascript
It is possible to set an absolute positioning to the title, but this would be too narrow to the paragraph-text itself, as no margin can be set.
Here is a JSFiddle
Now, how does one style a box with :after as a title on top, that also looks good when no title is set?
main {
width: 50%;
display: block;
place-items: center;
margin: auto;
}
p.note {
border: 3px solid red;
border-radius: 3px;
padding: 1em;
position: relative;
}
p.note::before {
margin: auto 0 0.5em 0.5em;
float: right;
}
p.note[title]::after {
content: attr(title);
position: relative;
font-weight: bold;
top: 0;
left: 1em;
}
.icon::before {
font-size: 2em;
content: "#";
}
<html>
<body>
<main>
<p class="note icon" title="This is a title">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolorem quidem non placeat quibusdam velit, dicta adipisci saepe magnam fuga debitis qui, minima, eius error laboriosam distinctio eos natus et!
</p>
</main>
</body>
</html>
What it looks like:
How it should look like:
A crazy idea using shape-outside. The trick is to use the before for the title where you apply float and after for the icon having position:absolute then the shape-outside will create a particular shape in order to simulate the float behaviour around the icon.
main {
width: 50%;
display: block;
margin: auto;
text-align:justify;
}
p.note {
border: 3px solid red;
border-radius: 3px;
padding: 1em;
position: relative;
}
p.note::after {
margin: auto 0 0.5em 0.5em;
position:absolute;
top: 1em;
right: 0.5em;
}
p.note[title]::before {
content: attr(title);
display:block;
height:3.5em;
float:right;
width:100%;
text-align:center;
font-weight: bold;
shape-outside:polygon(0 0,100% 0,100% 100%,calc(100% - 3em) 100%,calc(100% - 3em) calc(100% - 2em),0 calc(100% - 2em));
/* To illustrate the shape */
background:
linear-gradient(rgba(255,255,0,0.3) 0 0) top/100% calc(100% - 2em) no-repeat,
linear-gradient(rgba(255,255,0,0.3) 0 0) bottom right/3em 3em no-repeat;
border:1px solid rgba(0,0,0,0.2);
/**/
}
.icon::after {
font-size: 2em;
content: "#";
}
.icon:not([title])::after {
display:none;
}
.icon:not([title])::before {
font-size: 2em;
content: "#";
margin: auto 0 0.5em 0.5em;
float:right;
}
<main>
<p class="note icon" title="This is a title">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolorem quidem non placeat quibusdam velit, dicta adipisci saepe magnam fuga debitis qui, minima, eius error laboriosam distinctio eos natus et!
</p>
</main>
<main>
<p class="note icon" >
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolorem quidem non placeat quibusdam velit, dicta adipisci saepe magnam fuga debitis qui, minima, eius error laboriosam distinctio eos natus et!
</p>
</main>
Or a basic idea like below:
main {
width: 50%;
display: block;
margin: auto;
text-align:justify;
}
p.note {
border: 3px solid red;
border-radius: 3px;
padding: 1em;
position: relative;
}
p.note::before {
margin: auto 0 0.5em 0.5em;
float: right;
}
p.note[title]::after {
content: attr(title);
position: absolute;
font-weight: bold;
top: 0.5em;
left: 0;
right:2em;
text-align:center;
}
p.note[title] {
padding-top:2em;
}
.icon::before {
font-size: 2em;
content: "#";
}
<main>
<p class="note icon" title="This is a title">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolorem quidem non placeat quibusdam velit, dicta adipisci saepe magnam fuga debitis qui, minima, eius error laboriosam distinctio eos natus et!
</p>
</main>
<main>
<p class="note icon" >
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolorem quidem non placeat quibusdam velit, dicta adipisci saepe magnam fuga debitis qui, minima, eius error laboriosam distinctio eos natus et!
</p>
</main>
since grid doesn't help enough, let's go back in time with display :table and display:table-caption to add another answer and see if that could work too for you ;)
* {
box-sizing: border-box;
}
main {
width: 50%;
min-width:450px;
display: block;
place-items: center;
margin: auto;
}
p.note {
font-size:clamp(12px, 4vw, 30px);
border: 3px solid red;
border-radius: 3px;
padding: 1em;
display: table;
padding-top: 1.5em;
}
p.note::before {
margin: auto 0 0.5em 0.5em;
float: right;
font-weight:bold;
color:tomato;
}
p.note[title]::after {
content: attr(title);
font-weight: bold;
display: table-caption;
margin-bottom: -1.6em;
text-align: center;
padding-right: 3em;
}
.icon::before {
font-size: 2em;
content: "#";
line-height: 0.25;
}
<main>
<p class="note icon" title="This is a title">
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Dolorem quidem non placeat quibusdam velit, dicta adipisci saepe magnam fuga debitis qui, minima, eius error laboriosam distinctio eos natus et!
</p>
</main>
I have some problem with creating inside border of image. Tried to do it with border, outline and box-shadow but didn't get the result.
HTML:
<div class="item">
<img src="https://i.ytimg.com/vi/vsZDSXlHqI4/maxresdefault.jpg" alt="">
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo blanditiis, distinctio. Odio eveniet vel nobis, consequuntur atque, dolorum debitis quae nesciunt esse quasi beatae, odit repudiandae dolore animi delectus ad nostrum, quas maiores hic labore?
Nisi, expedita sint, qui ullam itaque natus optio error accusantium placeat, culpa reiciendis, quos tempora.</p>
<button>Some action</button>
</div>
CSS:
div.item:hover {
//some code
img {
border-bottom: 5px solid #8cc34b;
margin-bottom: -5px;
}
}
My fiddle: JSFiddle
Here I got the outside border but I want to get inside border of image.
Thanks for help.
Wrap your img in div, and on hover use :after pseudo-element:
div.item {
min-height: 300px;
overflow: auto;
width: 300px;
background-color: white;
border: 2px solid #8cc34b;
border-radius: 5px;
text-align: center;
box-sizing: border-box;
-webkit-box-sizing: border-box;
}
div.item img {
width: 100%;
display: block;
}
div.item p {
text-align: left;
padding-left: 10px;
padding-right: 10px;
}
div.item button {
height: 35px;
width: 120px;
margin: 0 auto;
margin-bottom: 20px;
}
div.item .img-container {
position: relative;
}
div.item:hover h3 {
color: #8cc34b;
}
div.item:hover .img-container:after {
content: '';
position: absolute;
left: 0;
bottom: 0;
height: 5px;
width: 100%;
background-color: #8cc34b;
}
<div class="item">
<div class="img-container">
<img src="https://i.ytimg.com/vi/vsZDSXlHqI4/maxresdefault.jpg" alt="">
</div>
<h3>Title</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Illo blanditiis, distinctio. Odio eveniet vel nobis, consequuntur atque, dolorum debitis quae nesciunt esse quasi beatae, odit repudiandae dolore animi delectus ad nostrum, quas maiores hic labore?
Nisi, expedita sint, qui ullam itaque natus optio error accusantium placeat, culpa reiciendis, quos tempora.</p>
<button>Some action</button>
</div>
I also added display: block on img, because inline img creates extra whitespace below.
Another answer:
To create a color bar like in the image you liked to, I wrapped your image in a DIV with class x and added the following CSS (including a pseudo element):
img {
width: 100%;
}
.x {
display: block;
position: relative;
}
.x:before {
content: '';
position: absolute;
z-index: -1;
bottom: 7px;
left: 0;
right: 0;
height: 5px;
background-color: #8cc34b;
}
Instead of a hover rule for the image, I just make the x DIV visible by changing its z-index:
div.item:hover {
h3 {
color: #8cc34b;
}
.x:before {
z-index: 1;
}
}
Adjust the bottom setting as desired to move it up or down:
https://jsfiddle.net/9wLx9p0f/5/
We can simply do this with outline-offset property:
outline: 1px solid #fff;
outline-offset: -10px;
Try this in the div you wants, if it works for you.
The .speech height may vary therefore looking for solution to make .speech::after's width same as .speech's height.
ideal result
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.speech {
width: 250px;
padding: 1rem;
background-color: tomato;
color: white;
border: 1px solid;
position: relative;
}
.speech::after {
content: '';
position: absolute;
top: 0;
left: 100%;
border: 3px solid deepskyblue;
height: 100%;
padding-left: 50%;
background: linear-gradient(45deg, transparent 50%, green 0%);
transform: translateX(-50%) rotate(45deg);
}
<div class="speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>
You don't necessarily need pseudo elements for this, as long as you use CSS gradients, since all browsers that support gradients also support multiple backgrounds:
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.speech {
width: 250px;
padding: 1rem;
background: linear-gradient(tomato,tomato),
linear-gradient(to top right, tomato 49%,transparent 51%),
linear-gradient(to bottom right, tomato 49%,transparent 51%);
background-size: calc(100% - 30px) 100%, 30px 50%, 30px 50%;
background-position: 0 0, 100% 0, 100% 100%;
background-repeat: no-repeat;
color: white;
border: 1px solid;
position: relative;
}
<div class="speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>
Defining a clip-path will give you the intended result.
The clip-path CSS property creates a clipping region that defines what
part of an element should be displayed. Those portions that are inside
the region are shown, while those outside are hidden. The clipping
region is a path specified either as a URL referencing inline or
external SVG, or as a shape, such as a circle().
clip-path - CSS | MDN
var addText = "Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.";
jQuery('.add-text').on('click', function(){
jQuery('.alt-speech').append(addText);
});
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column; /* for the sake of demonstration */
}
.speech {
width: 250px;
padding: 1rem;
background-color: tomato;
color: white;
border: 1px solid;
position: relative;
}
.speech::after {
content: '';
position: absolute;
top: 0;
left: 100%;
border: 3px solid deepskyblue;
height: 100%;
padding-left: 50%;
background: linear-gradient(45deg, transparent 50%, green 0%);
transform: translateX(-50%) rotate(45deg);
}
/* Additional */
.alt-speech {
width: 250px;
padding: 1rem;
background-color: tomato;
color: white;
border: 1px solid;
position: relative;
}
.alt-speech:after {
content: "";
width: 50%;
background: tomato;
-webkit-clip-path: polygon(0 0, 0% 100%, 30% 50%);
clip-path: polygon(0 0, 0% 100%, 30% 50%);
top: 0;
bottom: 0;
left: 100%;
position: absolute;
}
.add-text {
transition: .7s;
color: white;
background: tomato;
padding: 10px 20px;
cursor: pointer;
}
.add-text:hover {
background: #c12a0f;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="add-text">Add Text</div>
<div style="margin: 20px 0px"></div>
<div class="alt-speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>
Further Reading:
Creating Responsive Shapes With Clip-Path And Breaking Out Of The Box (Smashing Magazine)
NOTE:
This is an experimental technology, carefully review cross browser compatibility and support before implementing in production.
Cross browser compatibility & support Overview:
caniuse.com
clip-path - CSS | MDN
This is not what you actually asked for. So please correct me if I'am wrong. You asked for a bubble that grows width the height of the parent container. This is not the case with this answer. But I feel this is the desired effect anyways.
Instead of rotating an element by 45% this is using two pseudo elements and linear backgrounds to have a bubble effect.
The width is fixed and may be set according to your needs. But the bubble itself follows the height of any dynamic content.
.speech {
width: 250px;
padding: 1rem;
background-color: tomato;
color: white;
border: 1px solid;
position: relative;
}
.speech::before,
.speech::after {
content: '';
position: absolute;
left: 100%;
right: 0;
top: 0;
width: 45px;
height: 50%;
}
.speech::before {
background: linear-gradient(to top right, tomato 50%, transparent 50%);
}
.speech::after {
top: 50%;
background: linear-gradient(to bottom right, tomato 50%, transparent 50%);
}
<div class="speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>
<div class="speech">Very small</div>
<div class="speech">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</p>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</p>
</div>
Update your code like this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=0, width=device-width;" />
<meta name="format-detection" content="telephone=no">
<meta name="description" content="">
<link rel="shortcut icon" href="favicon.ico" />
<meta name="author" content="">
<style>
body {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
.speech {
width: 250px;
padding: 0px;
background-color: tomato;
color: white;
border: 1px solid;
position: relative;
}
.speech::after {
content: '';
position: absolute;
width: 0;
height: 0;
top:0px;
left:100%;
}
</style>
</head>
<body>
<div class="speech">Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem. Lorem ipsum dolor sit amet consectetur adipisicing elit. Facilis minima possimus, maxime, fugit dolorum optio, tempora et doloribus doloremque ullam inventore repellendus veniam modi quasi iusto numquam amet eos! Exercitationem.</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script>
$( document ).ready(function() {
var ht = $(".speech").height();
var ht1 = ht/2;
$("head").append($('<style>.speech:after { border-top: '+ht1+'px solid transparent; border-bottom: '+ht1+'px solid transparent; border-left: '+ht1+'px solid green;}</style>'));
});
</script>
</body>
</html>