CSS Image Split with Two Columns and a Split in the Center - html

I've looked a bit for this, and can't find it on SO. I basically have to put together a design as follows...
I'm using Bootstrap4 and I'm pretty good at CSS, and this is still giving me a bit of an issue. It should be full-screen, but I'd be open to giving it a max-width of 1400px.
My Idea: I currently had the idea of doing an element with the two elements on the side, and then use transform to rotate, and then put another element inside that has the background image and then uses transform to un-rotate it.
Here's my codepen to show what I've tried -
https://codepen.io/Gwapedwink/pen/ZaPvyo?editors=1100
<section>
<div class="image-splitter">
<div class="inner left">
<span style="background-image:url('http://placehold.it/940x240/222222/fff&text=left"></span>
</div>
<div class="inner right">
<span style="background-image:url('http://placehold.it/940x240/b4d455/fff&text=right"></span>
</div>
</div>
</section>
with the CSS of:
.image-splitter {
background-color: #f1f1f1;
position: relative; /* allows for absolute inside */
height: 240px; /* height of this section is 240px */
width: 100%;
overflow: hidden; /* important for this idea */
}
.image-splitter .inner {
position: absolute;
width:1000px;
height: 500px;
top:50%;
transform:translateY(-50%);
-webkit-transform:translateY(-50%);
overflow:hidden;
}
.image-splitter .inner.left {
right: 50%;
transform: rotate(5deg) translateY(-50%);
z-index:10;
}
.image-splitter .inner.right {
left: 50%;
z-index:9;
}
.image-splitter .inner span {
display: block;
position: absolute;
top: 50%;
height:350px;
width: 100%;
transform: translateY(-50%);
-webkit-transform: translateY(-50%);
/* background image properties */
background-position: center;
background-size: cover;
}
.image-splitter .inner.left span {
right: -50px;
transform: rotate(-5deg) translateY(-50%);
-webkit-transform: rotate(-5deg) translateY(-50%);
}
.image-splitter .inner.right span {
left: 0;
}
You can see that there are so many issues already, and I want to know if I'm missing something that's available. You can see that the text in the codepen should be level, but it isn't.
Thanks in advance!

I think the vertical misalignment of the texts on the two sides is due to how placehold.it renders the text onto the images, and not related to your code. If you observe the two sample images –"left" and "right"– alone, you will notice that the baseline of the printed texts are already on different heights. Here is an overlay of the two images in question:
This thing happens because of the two strings have different overall heights. So by using texts of similar heights could solve your issue with the placeholder images. I would use square brackets to equalise the height like so: "[left]" and "[right]".
To demonstrate this, I used another approach to achieve your splitted image effect. This one makes use of the clip-path css property, which is not available on IE and Edge, so it might or might not work for you in production. On the other hand, this one simplifies the css big time.
body { margin: 0; }
.image-splitter {
position: relative;
}
.inner {
overflow: hidden;
width: 60%;
height: 240px;
background: transparent no-repeat center center / cover;
}
.right {
position: absolute;
top: 0;
right: 0;
-webkit-clip-path: polygon(calc(16.667% + 50px) 0%, 100% 0%, 100% 100%, 16.667% 100%);
clip-path: polygon(calc(16.667% + 50px) 0%, 100% 0%, 100% 100%, 16.667% 100%);
}
<section>
<div class="image-splitter">
<div class="inner left" style="background-image:url('http://placehold.it/940x240/222222/fff&text=[left]">
</div>
<div class="inner right" style="background-image:url('http://placehold.it/940x240/b4d455/fff&text=[right]">
</div>
</div>
</section>

After recommendations from #dference, it became clear to use clip-path. The issue is of browser compatibility.
So, I took his answer above and then converted it to using SVG - but also had to use foreignObject to allow Edge support.
<div class="image-splitter">
<div class="inner left" style="background-image:url('https://picsum.photos/760/240?image=1067"></div>
<div class="inner right">
<!-- SVG CLIP -->
<svg width="100%" height="240px">
<defs>
<clipPath id="clipPolygon">
<polygon points="0 240,2000 240,2000 0,50 0">
</polygon>
</clipPath>
</defs>
<foreignObject clip-path="url(#clipPolygon)" width="100%" height="100%">
<img src="https://picsum.photos/760/240?image=1049">
</foreignObject>
</svg>
<!-- / SVG CLIP -->
</div> <!-- /.inner.right -->
</div> <!-- /.image-splitter -->
Throw that in with the CSS
/* image splitter */
.image-splitter {
position: relative;
height: 230px;
overflow: hidden;
& .inner {
overflow: hidden;
width: 60%;
height: 240px;
background: transparent no-repeat center center / cover;
}
& .right {
position: absolute;
top: 0;
width:50%;
right: 0;
/*-webkit-clip-path: polygon(calc(16.667% + 50px) 0%, 100% 0%, 100% 100%, 16.667% 100%);
clip-path: polygon(calc(16.667% + 50px) 0%, 100% 0%, 100% 100%, 16.667% 100%);*/
/* Clipping */
-webkit-clip-path: polygon(0px 240px,2000px 240px,2000px 0px,50px 0px);
clip-path: url("#clipPolygon");
& img {
width: 100%;
min-height: 240px;
}
}
}
You can take a look at this at my codepen - and you can also see the neat way that I did the content splitter below also.

Related

How to make skew not affect gradient css

i'm trying to apply a gradient to a skewed div but the gradient starts where the skew starts and it doesn't apply the gradient i'm looking for no matter what angle i use.
This is the gradient i'm trying to replicate
but I get a very different result...the colors are off and it's too green on the right side of mine. You can notice that on the image above, the gradient starts at the little wedge at the bottom but mine starts on the entire bottom part.
.main {
height: 80vh;
background-color: white;
}
.skew-div {
height: 100%;
width: 100%;
position: absolute;
top: 0;
background: linear-gradient(180deg, #1D2345 0%, #242766 27.88%, #294B7C 52.91%, #2E6E92 76.86%, #40CE9C 104.51%);;
transform: skewY(-12deg);
transform-origin: 0;
}
<div class="main">
<div class="skew-div">
</div>
</div>
is this possible without just placing the image as a background?
Use clip-path
.main {
height: 80vh;
background-color: white;
position:relative;
}
.skew-div {
height: 100%;
width: 100%;
position: absolute;
top: 0;
background: linear-gradient(180deg, #1D2345 0%, #242766 27.88%, #294B7C 52.91%, #2E6E92 76.86%, #40CE9C 104.51%);
clip-path: polygon(0 0, 100% 0, 100% 70%, 0 100%);
}
<div class="main">
<div class="skew-div">
</div>
</div>
You can use clip-path property
.main {
height: 80vh;
background-color: white;
}
.skew-div {
height: 100%;
width: 100%;
position: absolute;
top: 0;
background: linear-gradient(180deg, #1D2345 0%, #242766 27.88%, #294B7C 52.91%, #2E6E92 76.86%, #40CE9C 104.51%);
;
clip-path: polygon(0 0, 100% 0, 100% 75%, 0% 100%);
}
<div class="main">
<div class="skew-div">
</div>
</div>
Instead of using transform: skewY() you may use clip-path property. transform sometimes creates some sudden confusing problems. That's why you should sometimes escape using that property. Else use it using proper Browser Vendor Prefixes.
If you feel any difficulty configuring clip-path property then you may use this 3rd party website for clip-path value generation =>
https://bennettfeely.com/clippy/

Avoid image stretch within a CSS octagon container

When I updated the octagon's background image, it seems to have stretched it. Before, with the same CSS and a different image, it was normal.
Here is the original photo. As you can see, it is NOT stretched:
Here is the octagon photo that is stretched:
Here is all the code affecting the octagon image:
img[Attributes Style] {
width: 300px;
height: 300px;
}
* {
box-sizing: border-box;
}
.octo {
transform: rotate(45deg);
}
.octo1 {
transform: rotate(-45deg);
}
.octo,
.octo div {
margin: 0 auto;
transform-origin: 50% 50%;
overflow: hidden;
width: 300px;
height: 300px;
}
<div class="octo">
<div class="octo1">
<img src="https://i.stack.imgur.com/5voQJ.jpg" alt="" width="300" height="300" />
</div>
</div>
Instead of using <img>, include the image as a background-image for a <span> element, and use background-size: cover on it. To position the image, adjust the background-position values.
.octo-image {
display: block;
width: 300px;
height: 300px;
background-position: center center;
background-size: cover;
}
* {
box-sizing: border-box;
}
.octo {
transform: rotate(45deg);
}
.octo1 {
transform: rotate(-45deg);
}
.octo, .octo div {
margin: 0 auto;
transform-origin: 50% 50%;
overflow: hidden;
width: 300px;
height: 300px;
}
<div class="octo">
<div class="octo1">
<span class="octo-image" style="background-image: url('https://i.stack.imgur.com/5voQJ.jpg')"></span>
</div>
</div>
Alternatively, you could use <img> with object-fit: cover as well, but then you have to use a polyfill to support IE11 and older:
.octo-image {
width: 300px;
height: 300px;
object-fit: cover;
object-position: center center;
}
* {
box-sizing: border-box;
}
.octo {
transform: rotate(45deg);
}
.octo1 {
transform: rotate(-45deg);
}
.octo, .octo div {
margin: 0 auto;
transform-origin: 50% 50%;
overflow: hidden;
width: 300px;
height: 300px;
}
<div class="octo">
<div class="octo1">
<img class="octo-image" src="https://i.stack.imgur.com/5voQJ.jpg"></span>
</div>
</div>
Use a square source image, not a landscape rectangle. Specifying the height and width of an image force it to be a square. Your image will get squished on the horizontal and stretched on the vertical since it is a landscape image. This has nothing to do with your octagon styling. See my below example:
<img src="https://i.stack.imgur.com/oiEvT.png" height="300" width="300" />
Alternatively, if you can't use a background image you could use the clip-path property to draw the octagon with a cleaner markup and a full-responsive behaviour
Codepen demo
Markup
<figure>
<img src="https://i.stack.imgur.com/5voQJ.jpg" alt=""/>
</figure>
CSS
/*
* The outer wrapper defines the shape and hides the overflow of the
* inner image. The max-width ensures the responsiveness.
*/
figure {
position: relative;
max-width: 300px;
overflow: hidden;
clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%,
70% 100%, 30% 100%, 0% 70%, 0% 30%);
}
/*
* This pseudoelement ensures to keep the correct aspect ratio
* through the padding-bottom property. Since the image should be
* squared, the padding must be 100% of the element width
*/
figure::before {
content: "";
display: inline-block;
padding-bottom: 100%;
}
/*
* Finally the image must be properly centered (it requires some
* adjustment if the subject it's not aligned in its canvas),
* the height is 100% of its container but the width is not
* specified so the image can scale, keeping its natural
* aspect ratio
*/
img {
position: absolute;
left: 45%;
height: 100%;
transform: translateX(-50%);
}
Final result

Parallax div sections with a slant

How would I go about create several homepage sections, all with parallax background images and a slanted edge?
This is the design I'm trying to create: http://prnt.sc/ea0avx
If it helps, I'm building within Wordpress using Avada theme as my base.
https://www.viget.com/articles/angled-edges-with-css-masks-and-transforms
The Author details how to write css such that the sections have angled borders.
You can just transform the angled divs and over lap them off the screen.
<style>
body {
margin: 0;
}
.angle {
margin: -75px;
top: 350px;
height: 400px;
background: green;
transform: rotate(-5deg);
z-index: 5;
}
.revAngle {
margin: -75px;
width: 150%;
height: 400px;
background: green;
transform: rotate(5deg);
z-index: 5;
}
.strait {
height: 500px;
background: pink;
}
</style>
<html>
<div class="strait"></div>
<div class="angle"></div>
<div class="strait"></div>
<div class="revAngle"></div>
<div class="strait"></div>
</html>
http://codepen.io/kevinlbatchelor/pen/ggJmYK
To achieve a parallax background effect use something along these lines of code.
Example:
.parallaxdiv {
/* The image used */
background-image: url("img_parallax.jpg");
/* The Full height */
height: 100%;
/* Create the parallax scrolling effect */
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
I am not exactly sure what you mean by a slanted edge , but you can try to use CSS clip-paths to achieve a slanted affect.
An example:
.img {
-webkit-clip-path: polygon(0 0, 100% 0, 100% 96%, 0 100%);
clip-path: polygon(0 0, 100% 0, 100% 96%, 0 100%);
}
Please vote up if it helps !

Create a diagonal background image [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I want to create a diagonal background image as seen in the attached image. I can create a diagonal line using linear-gradient however as I have two different angles this didn't work.
Using Linear Gradients:
This can be done using multiple background images and positioning them accordingly. In the snippet below I've used 3 different layers - one for the top angle (a triangle which is transparent for 50% and is colored for the rest), one for the middle which is essentially nothing but a solid colored rectangle, this is created using linear gradients as it is easier to control the dimensions of an image and finally one for the bottom angle (same approach as the top one but this has a different height and so different angle.)
The output is also responsive as you can see by hovering the element in the below snippet. In the 2nd div, I've set different colors for each image so that you can see how it is formed.
div {
height: 300px;
width: 100%;
background: linear-gradient(to bottom right, transparent 50%, lightblue 51%), linear-gradient(lightblue, lightblue), linear-gradient(to top right, transparent 50%, lightblue 51%);
background-size: 100% 30px, 100% calc(100% - 130px), 100% 100px;
background-position: top left, left 30px, bottom left;
background-repeat: no-repeat;
transition: all 1s ease; /* just for demo */
}
/* just for demo */
div {
margin-bottom: 10px;
}
div:hover {
height: 400px;
}
div:nth-of-type(2) {
background: linear-gradient(to bottom right, transparent 50%, lightblue 51%), linear-gradient(lightpink, lightpink), linear-gradient(to top right, transparent 50%, lightgreen 51%);
background-size: 100% 30px, 100% calc(100% - 130px), 100% 100px;
background-position: top left, left 30px, bottom left;
background-repeat: no-repeat;
}
<div></div>
<div></div>
Using SVG: recommended
This is the approach that I generally recommend and is the best. It involves creating the shape using SVG and then placing it absolutely behind the div element.
div {
position: relative;
height: 300px;
width: 100%;
}
svg {
position: absolute;
height: 100%;
width: 100%;
}
polygon {
fill: lightblue;
}
<div>
<svg viewBox='0 0 300 100' preserveAspectRatio='none'>
<polygon points='0,10 300,0 300,100 0,75z' />
</svg>
</div>
Using Clip-path:
Another approach that can be used is to position a pseudo-element behind the main div and then set a clip-path in the required shape to this pseudo-element.
Note: This snippet will currently work only in WebKit powered browsers. Firefox would need the clip-path to be created via SVG element whereas IE doesn't support it all.
div {
position: relative;
height: 300px;
width: 100%;
}
div:before {
position: absolute;
content: '';
height: 100%;
width: 100%;
background: lightblue;
-webkit-clip-path: polygon(0% 5%, 100% 0%, 100% 100%, 0% 75%);
clip-path: polygon(0% 5%, 100% 0%, 100% 100%, 0% 75%);
}
<div></div>
CSS Perspective
You can use a CSS Perspective Transform to create the shape you want.
div {
margin-top: 25px;
width: 500px;
height: 150px;
transform: perspective( 800px ) rotateY( -25deg );
background: blue;
}
<div></div>
CSS Tricks Docs
Perspective - CSS | MDN
You can apply perspective to the parent container of the rotated div to give it 3-dimensional depth from the front of the viewport.
N.B. For the difference between transform: perspective(value) and perspective: value, see the CSS Tricks Almanac entry on perspective:
Important: Please note the perspective property doesn't affect how the element is rendered; it simply enables a 3D-space for children
elements. This is the main difference between the transform: perspective() function and the perspective property. The first
gives element depth while the latter creates a 3D-space shared by all
its transformed children.
After applying a 3-dimensional depth to the parent container using perspective, you can then apply rotateY to the div you want to rotate.
Working Example:
section {
position: relative;
width: 600px;
perspective: 800px;
transform: translateX(-60px);
}
div:nth-of-type(1) {
position: absolute;
top:30px;
left: 0;
width: 100%;
height: 100px;
background-color: rgb(235,250,255);
transform: rotateY(320deg);
}
div:nth-of-type(2) {
position: absolute;
top: 0;
left: 220px;
width: 120px;
height: 140px;
background-color: rgb(103,201,236);
box-shadow: 6px 6px 6px rgba(127,127,127,0.5);
}
div:nth-of-type(3) {
position: absolute;
top: 24px;
left: 340px;
width: 120px;
height: 140px;
background-color: rgb(255,255,255);
box-shadow: 6px 6px 6px rgba(127,127,127,0.5);
}
<section>
<div></div>
<div></div>
<div></div>
</section>

CSS triangle containing text

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>