currently I use clip-path for containers that should be skew.
.box {
height: 150px;
line-height: 150px;
text-align: center;
background: yellow;
}
#first {
clip-path: polygon(0 20%, 100% 0%, 100% 80%, 0 100%);
}
#second {
clip-path: polygon(0 0, 100% 20%, 100% 100%, 0 80%);
}
#spacing {
height: 100px;
}
<div id="first" class="box">
<p>
first container with a very very very long text. It's really long and won't fit here. Some text may disappear when the screen size gets smaller.
</p>
</div>
<div id="spacing">
</div>
<div id="second" class="box">
<p>
second container with a longer text
</p>
</div>
If the window gets smaller the text will not break into a new line it will just disappear.
How can I make the missing part of the text appear in the next line?
You can find an example of what I want to do on this page
https://www.thenativeweb.io/#
I believe below approach solves your issue. I deleted defined height and line-height for #box, and added padding: 30px 0, so to make some space to clip. Now text acts more naturally. You can adjust precise values.
.box {
height: auto;
text-align: center;
background: yellow;
padding: 30px 0;
}
#first {
clip-path: polygon(0 20%, 100% 0%, 100% 80%, 0 100%);
}
#second {
clip-path: polygon(0 0, 100% 20%, 100% 100%, 0 80%);
}
#spacing {
height: 100px;
}
<div id="first" class="box">
<p>
first container with a very very very long text. It's really long and won't fit here. Some text may disappear when the screen size gets smaller.
</p>
</div>
<div id="spacing">
</div>
<div id="second" class="box">
<p>
second container with a longer text
</p>
</div>
"If the window gets smaller the text will not break into a new line it will just disappear." - problem is coming because of line-height of box class and have to remove height:150px from box class.
.box {
height: auto;
line-height: auto;
text-align: center;
background: yellow;
padding: 80px 20px;
}
#first {
clip-path: polygon(0 20%, 100% 0%, 100% 80%, 0 100%);
}
#second {
clip-path: polygon(0 0, 100% 20%, 100% 100%, 0 80%);
}
#spacing {
height: 100px;
}
<div id="first" class="box">
<p>
first container with a very very very long text. It's really long and won't fit here. Some text may disappear when the screen size gets smaller.
</p>
</div>
<div id="spacing">
</div>
<div id="second" class="box">
<p>
second container with a longer text
</p>
</div>
Related
I need to find a solution to keep the cropped image but have content sit inside with an opacity filter on the div. The problem I'm facing is that it wont match the angles and i cant use an overlap hidden, need to find a solution.... can anyone help with this shame you cant use an ::after on image to add filter div to darken a section :(
.promo {
position: relative;
}
.promo img {
-webkit-clip-path: polygon(0 16%, 100% 0, 100% 100%, 0% 84%);
clip-path: polygon(0 16%, 100% 0, 100% 100%, 0% 84%);
}
.promo__content {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 50%;
height: 100% color: #fff;
background: black;
}
<div class="promo">
<img src="https://i.picsum.photos/id/100/600/600.jpg" >
<div class="promo__content">
Content Here
</div>
</div>
Example of what I'm trying to do black box in the angled image the black box will be see through
Apply the clip-path to the whole container and not only the image to get what you want:
.container {
margin:50px 0;
clip-path:polygon(0 16%, 100% 0, 100% 100%, 0% 84%);
display:flex;
}
.box {
width:30%;
padding:80px;
box-sizing:border-box;
background:#000;
color:#fff;
}
.img {
width:70%;
background:url(https://i.picsum.photos/id/1074/1000/1000.jpg) center/cover;
}
<div class="container">
<div class="box">
some text here<br>
some text here<br>
some text here<br>
some text here<br>
some text here<br>
</div>
<div class="img"></div>
</div>
Currently using this CSS for a bottom slant going up from left to right:
clip-path: polygon( 0 0, 100% 0, 100% calc(100% - 3vw), 0 100% );
It works very well for a responsive solution but having a hard time figuring out how to do this for a responsive solution for a slant at the top of the div going down from left to right.
I tried this:
clip-path: polygon( 0 0, 100% calc(100% - 29vw), 100% 100%, 0 100% );
Thank you!
You can adjust like below. You make the second point to start lower by 3vw and you put back the other one to 100%
.box {
height: 100px;
background: red;
clip-path: polygon( 0 0, 100% 3vw, 100% 100%, 0 100%);
/* (0,0) ----------------- (100%,0)
| |<---------(100%,3vw)
| |
| |
| |
(0,100%) ----------------- (100%,100%)
}
<div class="box">
</div>
And like this if you want from right to left:
.box {
height: 100px;
background: red;
clip-path: polygon( 0 3vw, 100% 0, 100% 100%, 0 100%);
}
<div class="box">
</div>
On the sides:
.box {
height: 100px;
background: red;
clip-path: polygon( 0 0, calc(100% - 3vw) 0, 100% 100%, 0 100%);
}
<div class="box">
</div>
If you want a more supported way, you can consider multiple background like below:
.box {
height: 100px;
margin:5px;
padding-top:3vw;
background:
/*a triangle shape on the padding-top area*/
linear-gradient(to bottom var(--d,left),transparent 48%,red 50%) top/100% 3.1vw no-repeat,
/*color the content and not the padding-top*/
linear-gradient(red,red) content-box;
}
<div class="box">
</div>
<div class="box" style="--d:right">
</div>
currently I have a div container with text in it.
div {
height: 200px;
background: red;
}
p {
text-align: center;
}
<div>
<p>
Text goes here
</p>
</div>
and I want this div container being a parallelogram with a vertically centered text in it.
div {
height: 200px;
background: red;
clip-path: polygon(0 25%, 100% 0, 100% 25%, 0 50%);
}
p {
text-align: center;
}
<div>
<p>
Text goes here
</p>
</div>
as you can see here, the text completely disappears because the css only works for the div container.
How can I make the text appear in the vertical center of this parallelogram?
Edit:
I don't know if using
clip-path: polygon(0 25%, 100% 0, 100% 25%, 0 50%);
is the best way to create a div container that is skew.
Use gradient to create the shape as background and you simply need to center the text using any common way. You will have better support than clip-path.
div.container {
height: 120px;
line-height:120px;
background-image:
/*Top triangle*/
linear-gradient(to bottom right,transparent 49%,red 51%),
/*Bottom triangle*/
linear-gradient(to top left,transparent 49%,red 51%);
background-position:top, bottom; /* One on the top and the other on the bottom*/
background-size:100% 50%; /*both will be 100% width and 50% height*/
background-repeat:no-repeat; /*don't repeat*/
}
p {
text-align: center;
}
<div class="container">
<p>
Text goes here
</p>
</div>
And if you want to rely on clip-path better use these values to cover the whole div and you simply need to adjust the height of div to control the height of shape:
div.container {
height: 120px;
line-height:120px;
background:red;
-webkit-clip-path: polygon(0 50%, 100% 0%, 100% 50%, 0% 100%);
clip-path: polygon(0 50%, 100% 0%, 100% 50%, 0% 100%);
}
p {
text-align: center;
}
<div class="container">
<p>
Text goes here
</p>
</div>
I'm trying to get two images float next to each other with the shape-outside property. To be specific, I have two triangle-shaped .png images, which would make up a rectangle if put next to each other. Img1 should be on the left and Img2 on the right, and they're cut so that the diagonal goes from top right to bottom left.
With shape-outside I managed to get the text "hug" the diagonal border of the images, so something is working alright. The darn images just won't pop next to each other.
<style>
.myclass {
height: auto;
width: 100%;
}
.myclass img:first-child {
-webkit-shape-outside: polygon(0 0, 0 100%, 100% 0);
float: left;
width: 80%;
background-color: lightgray;
-webkit-clip-path: polygon(0 0, 0 100%, 100% 0);
}
.myclass img:nth-child(2) {
-webkit-shape-outside: polygon(100% 0, 100% 100%, 0 100%);
float: right;
width: 80%;
background-color: lightgray;
-webkit-clip-path: polygon(100% 0, 100% 100%, 0 100%);
}
</style>
<div class='myclass'>
<img src='img/img1.png'>
<img src='img/img2.png'>
</div>
<div class='myclass'>
<img src='img/img1.png'>
<img src='img/img2.png'>
</div>
I realize that I could achieve this by doing the image in Photoshop but for linking functionality I'd prefer them to stay as separate elements. Also, absolute positioning could work but that would require quite a lot of media queries as I want the site to be responsive and the amount of this kind of blocks varies and can be quite a few.
Reason:
The reason why they images don't pop up next to each other is because they both have width: 80%.
The clip-path applied to the element will clip into the required shape and the shape-outside setting will make inline text wrap around based on the shape but neither of them will change the shape of the bounding box of the img elements (which will remain square/rectangular).
In the below screenshot, the darker overlay (on top of the image) is the shape created through shape outside setting whereas the lighter overlay (it is there above the image also but is invisible due to the darker overlay's presence) represents the bounding box of the element and it is still rectangular.
This means that both the images can't be placed on the same line and so the second will automatically get pushed below. They can never be set on the same line as long as their combined width is > 100%. When the width of the two img elements is set to 50%, we can see that both of them appear on same line and that inline text wraps around in accordance with the shape on either side. So, there is nothing actually wrong with the shape-outside or the clip-path.
.myclass {
clear: both;
height: auto;
width: 100%;
}
.myclass img:first-child {
float: left;
width: 50%;
background-color: lightgray;
-webkit-shape-outside: polygon(0% 0%, 0% 100%, 100% 0%);
-webkit-clip-path: polygon(0% 0%, 0% 100%, 100% 0%);
}
.myclass img:nth-child(2) {
float: right;
width: 50%;
background-color: lightgray;
-webkit-shape-outside: polygon(100% 0%, 100% 100%, 0% 100%);
-webkit-clip-path: polygon(100% 0%, 100% 100%, 0% 100%);
}
<div class='myclass'>
<img src='http://lorempixel.com/800/200/nature/1'>
<img src='http://lorempixel.com/800/200/nature/2'>
Lorem ipsum dolor sit amet, some very lengthy inline content which is added to demonstrate how the content wraps around in accordance with the shapes.
</div>
Solution 1: Absolute Positioning
One solution to your problem is to use absolute positioning (I did see your statement in question but it is still an option). But then there is no need for shape-outside property itself because there is nothing to wrap around.
.myclass {
position: relative;
height: auto;
width: 100%;
}
.myclass img:first-child {
position: absolute;
width: 100%;
background-color: lightgray;
-webkit-clip-path: polygon(0% 0%, 0% 100%, 100% 0%);
}
.myclass img:nth-child(2) {
position: absolute;
right: 0px;
width: 100%;
background-color: lightgray;
-webkit-clip-path: polygon(100% 0%, 100% 100%, 0% 100%);
}
<div class='myclass'>
<img src='http://lorempixel.com/800/200/nature/1'>
<img src='http://lorempixel.com/800/200/nature/2'>
</div>
Solution 2: SVG recommended
As Paulie_D had mentioned in comments, your best bet would be to use SVG if you don't want to use absolute positioning. While we would still need to give (x,y) coordinates for the image tags as though we are doing absolute positioning, SVGs are by default responsive (they auto-adapt) and so the need for responsiveness is handled implicitly.
svg image:nth-of-type(1) {
-webkit-clip-path: url(#clipper-left);
clip-path: url(#clipper-left);
}
svg image:nth-of-type(2) {
-webkit-clip-path: url(#clipper-right);
clip-path: url(#clipper-right);
}
svg {
width: 100vw;
height: 40vh;
}
body {
margin: 0;
padding: 0;
}
<svg viewBox='0 0 900 400' preserveAspectRatio="none">
<defs>
<clipPath clipPathUnits="objectBoundingBox" id="clipper-left">
<path d="M0,0 1,0 0,1z" />
</clipPath>
<clipPath clipPathUnits="objectBoundingBox" id="clipper-right">
<path d="M1,0 0,1 1,1z" />
</clipPath>
</defs>
<image xlink:href="http://lorempixel.com/900/400/nature/1" x="0" y="0" height="400px" width="900px" />
<image xlink:href="http://lorempixel.com/900/400/nature/2" x="0" y="0" height="400px" width="900px" />
</svg>
I have a weird problem at hand and I am struggling to find a solution.
I have created a triangle <div> "container" using only CSS but what I would like now is to insert some text inside the container.
The solution I am aiming for has to contain the text within the boundaries of the triangle no matter how much text is inserted as I am looking to create thumbnails.
An example can be found here [note; this example is very basic and only shows the way I have chosen to create the triangle]
Pushing it a little further, I want to create one triangle facing up and one facing down and the text has to be at the base of each one, so for the 1st triangle the text will be at the bottom and for the 2nd at the top, plan B is just to center the text within the triangle both vertically and horizontally.
CSS:
.up {
text-align:right;
width: 0px;
height: 0px;
border-style: inset;
border-width: 0 100px 173.2px 100px;
border-color: transparent transparent #007bff transparent;
float: left;
transform:rotate(360deg);
-ms-transform:rotate(360deg);
-moz-transform:rotate(360deg);
-webkit-transform:rotate(360deg);
-o-transform:rotate(360deg);
}
HTML:
<div class="up">
<p>some information text goes here<p>
</div>
For your plan B (to center the text within the triangle both vertically and horizontally), which I prefer as solution, you could add this css rule:
.up p {
text-align: center;
top: 80px;
left: -47px;
position: relative;
width: 93px;
height: 93px;
margin: 0px;
}
Try it here:
.up {
width: 0px;
height: 0px;
border-style: inset;
border-width: 0 100px 173.2px 100px;
border-color: transparent transparent #007bff transparent;
float: left;
transform: rotate(360deg);
-ms-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-o-transform: rotate(360deg);
}
.up p {
text-align: center;
top: 80px;
left: -47px;
position: relative;
width: 93px;
height: 93px;
margin: 0px;
}
<div class="up">
<p>some information text goes here
<p>
</div>
View on JSFiddle
How can you fit text inside the triangle, no matter how much text there is? As far as I know, it is not possible with CSS alone. The text that can't fit in will overflow, and you'd need to use Javascript to adjust the font size accordingly to fit all of them.
But suppose that you want a reasonable amount of text to fit inside a right triangle (base is on the left, pointing to the right), here is an approach:
create a container with fixed width and height to hold the text, and the shapes.
inside the container, create two divs floated to the right. Each has width 100% and height 50%, shape-outline and clip-path as polygon.
give these divs background color similar to the background of the rendered page.
The idea is that the part outside these two divs will take the shape of a triangle we are looking for.
In CSS, elements are rectangles, where you realize it or not. It's not about drawing a triangle. It's about creating neighboring elements that suggest a triangle. Hope that makes sense.
.main {
width: 400px;
height: 200px;
position: relative;
background: peachpuff;
}
.top, .bottom {
width: 100%;
height: 50%;
background: white;
}
.top {
-webkit-shape-outside: polygon(0% 0, 100% 0%, 100% 100%);
shape-outside: polygon(0% 0, 100% 0%, 100% 100%);
float: right;
-webkit-clip-path: polygon(0% 0, 100% 0%, 100% 100%);
clip-path: polygon(0% 0, 100% 0%, 100% 100%);
}
.bottom {
height: 50%;
float: right;
bottom: 0;
clip-path: polygon(0% 100%, 100% 100%, 100% 0%);
shape-outside: polygon(0% 100%, 100% 100%, 100% 0%);
}
<div class="main">
<div class="top"></div>
<div class="bottom"></div>
<p>
When should one use CSS versus SVG? Use CSS for simple shapes. HTML elements are rectangles, so all you are doing is creating an illusion of shapes. Sometimes this can become a deep rabbit hole. Instead, use SVG for complex shapes.
</p>
</div>