Maintain angle of clip-path on viewport width and height changes - javascript

I am trying to create something similar to the example, where the angle of the clip path needs to remain the same on resizing. Both on height and width changes to the viewport. I have tried using calc(100% - 6vw) (as an example) but this doesn't maintain the exact angle.
The reason for this is I will have multiple elements that are required to have mirroring angles in a responsive environment.
Can this be achieved using CSS and calc alone, or is there a JS-based math solution to resolve it? I guess this is where trigonometry comes in and I believe what I need is the opposite side length being relative to the height of the adjacent/height of the content area (however, I failed maths...) to maintain the same angle.
Some work that I have done based on a mock-up I am working from. The angle (I think) I need to find is 14deg. I've based this on the adjacent being 899px and the opposite 229px.
Any help is much appreciated.
body {
margin: 0;
}
.slide {
background-color: red;
height: 100vh;
position: relative;
}
.slide_content {
background-color: blue;
padding: 50px 30px;
color: #fff;
position: absolute;
width: 70%;
left: 0;
bottom: 0;
clip-path: polygon(0 0, 90% 0, 102% 100%, 0% 100%);
}
.slide_content-top {
background-color: orange;
padding: 50px 30px;
color: #fff;
position: absolute;
width: 70%;
right: 0;
top: 0;
padding-left: 100px;
clip-path: polygon(0 0, 100% 0, 100% 100%, 10% 100%);
}
<div class="slide">
<div class="slide_content-top">
<h2>More content here</h2>
</div>
<div class="slide_content">
<h2>Some text goes here</h2>
</div>
</div>
Another Example
So how I would apply this is as follows - The shape in red is where text content would be placed. The area in blue is the right-angle triangle I need to create. The triangle would need to maintain it's ratio as the content area grows or shrinks. The base of this triangle (width: 85px in this example) would need to resize in proportion to the height of the content area (currently height: 200px).
The only values I would know are the acute angle between the hypotenuse and the adjacent (14deg), and the length of the adjacent would be calculated by getting it from the content area's current height.
.shape {
width: 400px;
height: 200px;
background-color: red;
position: relative;
}
.shape:after {
content: '';
position: absolute;
width: 85px;
height: 200px;
background-color: blue;
top: 0;
bottom: 0;
right: -85px;
clip-path: polygon(0 0, 0 0, 100% 100%, 0% 100%);
}
<div class="shape"></div>
A further update
This is what I have achieved so far. Which I think does part of what I am looking for. Creates a right-angle that maintains to same ratio on resizing. However, I'm not entirely sure how robust this particular snippet I've created is.
function getTanFromDegrees(degrees) {
return Math.tan(degrees * Math.PI / 180);
}
function createRightAngleTriangle() {
const shapes = document.querySelectorAll('.shape');
shapes.forEach(shape => {
const shapeContent = shape.querySelector('.shape-content');
const shapeTri = shape.querySelector('.shape-tri');
const shapeHeight = shapeContent.offsetHeight;
const tan = getTanFromDegrees(14);
const getLength = Math.floor(tan * shapeHeight);
shapeTri.style.height = shapeHeight + 'px';
shapeTri.style.width = getLength + 'px';
})
}
window.addEventListener('load', createRightAngleTriangle);
window.addEventListener('resize', createRightAngleTriangle);
.shape {
display: flex;
align-items: flex-start;
}
.shape-content {
padding: 20px;
font-size: 22px;
}
.shape-tri {
background-color:green;
clip-path: polygon(0 0, 0 0, 100% 100%, 0% 100%);
}
.shape-1 .shape-content {
background-color: red;
}
.shape-2 .shape-content {
background-color: blue;
}
<div class="shape shape-1">
<div class="shape-content">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Maiores aut deleniti dolor doloremque, nesciunt minus voluptatem! Voluptas odio obcaecati vitae?
</div>
<div class="shape-tri"></div>
</div>
<div class="shape shape-2">
<div class="shape-content">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Maiores aut deleniti dolor doloremque, nesciunt minus voluptatem! Voluptas odio obcaecati vitae? Lorem ipsum, dolor sit amet consectetur adipisicing elit. Ut, eos.
</div>
<div class="shape-tri"></div>
</div>

You can try like below. the value 0.25 is tan(14deg)
body {
margin: 0;
}
.slide {
background-color: red;
min-height: 100vh;
display:grid;
grid-auto-rows:1fr;
color: #fff;
}
.slide_content {
background: blue;
box-shadow: 200px 0 blue;
padding: 30px;
width: 70%;
margin-top:auto;
clip-path: polygon(0 0, 100% 0, calc(100% + 0.25*100vmax) 100vmax, 0 100vmax);
}
.slide_content-top {
background-color: orange;
box-shadow: -200px 0 orange;
padding: 30px;
width: 70%;
margin-left: auto;
margin-bottom:auto;
clip-path: polygon(calc(-0.25*100vmax) -100vmax ,100% -100vmax, 100% 100%, 0 100%);
}
<div class="slide">
<div class="slide_content-top">
<h2>More content here</h2>
</div>
<div class="slide_content">
<h2>Some text <br> goes here</h2>
</div>
</div>

Related

changing image position using css

I would like to change the position of this image and put to the right of the content
do you know how? and i also don't understand why the image outside the article shouldn't it be inside? Thank you can i do that?
I wrote this code:
your text
section {
display : flex;
margin-left : auto;
margin-right : auto;
margin-bottom : 20px;
margin-top : 20px;
height : 50vh;
width : 60vw;
border-radius : 3px;
box-shadow : -10px -10px 15px rgba(255,255,255, 0.5)
, 10px 10px 15px rgba( 70, 70, 70, 0.12);
}
.art-fle1 ,
.art-fle2 {
height : 90%;
width : 100%;
margin-top : auto;
}
.content-text {
width : 50%;
height : 80%;
padding-left : 15px;
}
.burger {
width : 270px;
float : right;
}
<main>
<section class="first-section">
<article class="art-fle1" class="a1">
<div class="continer A">
<div class="content-text">
<h1>Header 1</h1>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quaerat corporis voluptate vel ab consectetur repudiandae sunt accusantium. Perspiciatis, minima voluptatem!
</p>
</div>
<div class="burger">
<img src="food/burger.jpg" alt="" width="270px">
</div>
</div>
</article>
</section>
</main>
You need to assign .container-A as display: flex with justify-content: space-between. You don't really need a div to contain the burger image either, but I included it to make the DOM as similar to your original question as possible.
I'm linking the mdn web docs for justify-content and
align-items as well. Hope this helps!
https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content
https://developer.mozilla.org/en-US/docs/Web/CSS/align-items
<!DOCTYPE html>
<html>
<head>
<title>Stack Overflow</title>
<style>
section {
display : flex;
margin-left : auto;
margin-right : auto;
margin-bottom : 20px;
margin-top : 20px;
height : 50vh;
width : 60vw;
border-radius : 3px;
box-shadow : -10px -10px 15px rgba(255,255,255, 0.5)
, 10px 10px 15px rgba( 70, 70, 70, 0.12);
}
.art-fle1 ,
.art-fle2 {
height : 90%;
width : 100%;
margin-top : auto;
}
.content-text {
width : 50%;
height : 80%;
padding-left : 15px;
}
.burger {
width : 270px;
float : right;
}
.container-A {
display: flex;
justify-content: space-between;
}
</style>
</head>
<body>
<main>
<section class="first-section">
<article class="art-fle1" class="a1">
<div class="container-A">
<div class="content-text">
<h1>Header 1</h1>
<p>
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Quaerat corporis voluptate vel ab consectetur repudiandae sunt accusantium. Perspiciatis, minima voluptatem!
</p>
</div>
<div class="burger">
<img src="food/burger.jpeg" alt="" width="270px">
</div>
</div>
</article>
</section>
</main>
</body>
</html>

Hide element if scrolled to maximum of container

I worked with this code:
$(document).ready(function() {
// Show left gradient if scrolled x value is greater than 0
$("#scroll-area").scroll(function() {
if ($("#scroll-area").scrollLeft() > 0) {
$("#left").css("display", "block");
}
// Hide left gradient if scrolled x value is 0
if ($("#scroll-area").scrollLeft() == 0) {
$("#left").css("display", "none");
}
// Calculate with of the scroll area
var fullWidth = $('#scroll-area')[0].scrollWidth;
// Doesn't work: Hide right gradient if scrolled to maximum
if ($("#scroll-area").scrollLeft() == fullWidth) {
$("#right").css("display", "none");
}
// Doesn't work: Show gradient if scrolled less than maximum
if ($("#scroll-area").scrollLeft() < fullWidth) {
$("#right").css("display", "block");
}
});
});
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 20px;
}
#container {
width: 50%;
height: 120px;
background-color: grey;
position: relative;
}
#scroll-area {
white-space: nowrap;
overflow-x: auto;
height: 100%;
}
#left,
#right {
width: 50px;
height: 100%;
position: absolute;
pointer-events: none;
top: 0;
}
#left {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0;
display: none;
}
#right {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
right: 0;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div id="container">
<div id="left"></div>
<div id="right"></div>
<div id="scroll-area">
<div id="text">Please scroll horizontally to the right side, and back again. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
</div>
</div>
If you scroll horizontally to the end of the #text element, the gradient on the right side should be hidden. If you scroll to the left side again, the gradient should be shown again.
Has anyone an idea how to program that?
It should work as you want. Basically i calculate scrollable area in fullWidth and compare it with scrollPosition
$("#scroll-area").scroll(function() {
var fullWidth = $('#scroll-area')[0].scrollWidth - $('#scroll-area')[0].clientWidth;
var scrollPosition = $(this).scrollLeft();
if (scrollPosition > 0 && scrollPosition <= fullWidth) {
$("#left").css("display", "block");
$("#right").css("display", "block");
} else if (scrollPosition == 0) {
$("#left").css("display", "none");
$("#right").css("display", "block");
} else if (fullWidth <= scrollPosition) {
$("#left").css("display", "block");
$("#right").css("display", "none");
}
console.log('Scroll pos',scrollPosition);
console.log('Full width', fullWidth);
});
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 20px;
}
#container {
width: 50%;
height: 300px;
background-color: grey;
position: relative;
}
#scroll-area {
white-space: nowrap;
overflow-x: auto;
height: 100%;
}
#left,
#right {
width: 50px;
height: 100%;
position: absolute;
pointer-events: none;
top: 0;
}
#left {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0;
display: none;
}
#right {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
right: 0;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div id="container">
<div id="left"></div>
<div id="right"></div>
<div id="scroll-area">
<div id="text">Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
</div>
</div>
You need to subtract the offsetWidth from the scrollWidth:
var fullWidth = $('#scroll-area')[0].scrollWidth - $('#scroll-area')[0].offsetWidth - 1 // -1 for browser compatibility
$(document).ready(function() {
// Show left gradient if scrolled x value is greater than 0
$("#scroll-area").scroll(function() {
if ($("#scroll-area").scrollLeft() > 0) {
$("#left").css("display", "block");
}
// Hide left gradient if scrolled x value is 0
if ($("#scroll-area").scrollLeft() == 0) {
$("#left").css("display", "none");
}
// Calculate with of the scroll area
var fullWidth = $('#scroll-area')[0].scrollWidth - $('#scroll-area')[0].offsetWidth - 1;
// Doesn't work: Hide right gradient if scrolled to maximum
if ($("#scroll-area").scrollLeft() >= fullWidth) {
$("#right").css("display", "none");
}
// Doesn't work: Show gradient if scrolled less than maximum
if ($("#scroll-area").scrollLeft() < fullWidth) {
$("#right").css("display", "block");
}
});
});
* {
margin: 0;
padding: 0;
font-family: sans-serif;
font-size: 20px;
}
#container {
width: 50%;
height: 120px;
background-color: grey;
position: relative;
}
#scroll-area {
white-space: nowrap;
overflow-x: auto;
height: 100%;
}
#left,
#right {
width: 50px;
height: 100%;
position: absolute;
pointer-events: none;
top: 0;
}
#left {
background: linear-gradient(90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
left: 0;
display: none;
}
#right {
background: linear-gradient(-90deg, orange 0%, rgba(0, 0, 0, 0) 100%);
right: 0;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<div id="container">
<div id="left"></div>
<div id="right"></div>
<div id="scroll-area">
<div id="text">Please scroll horizontally to the right side, and back again. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua.</div>
</div>
</div>

Vue JS fading animation with smooth height

I have a block when clicked it opens when clicked again closes I want to apply an animation to this block, I want to apply an animation like this
<template>
<div>
<button #click="show = !show">Click me</button>
<div v-show="show" class="anim-block"></div>
</div>
</template>
<script>
export default {
data() {
return {
show: false,
};
},
};
</script>
<style scoped>
.anim-block {
margin: 30px auto;
width: 280px;
height: 300px;
background: red;
}
</style>
You can also look at my code in codesandbox
You can do this with just a bit of CSS.
Essentially just use your parent anim-block as a mask and add a child div containing your content.
Child
position: absolute = So that it doesn't move with the parent animation
left: 50%; transform: translateX(-50%); = To center it within the page (according to your current code sandbox layout)
width: 280px; height: 300px; = Set the dimensions of the window
Parent
position: relative = To keep the child on the parent, not the page (absolute positioned elements get their origin from the closest relative positioned parent)
overflow: hidden = To mask out everything outside it while it animates
width: 0; height: 0; opacity: 0; = Set the starting state of the animation
transition: all 0.3s; = Transition the width and height when they change (can also set width and height independently but "all" is nice and succinct
Vue Component
Lastly, just add a dynamic class on your parent component when show = true.
<div :class="`anim-block ${show && 'open'}`">
With the final state of your animation in the .open class:
.open {
width: 280px;
height: 300px;
opacity: 1;
}
Final Result
Template:
<template>
<div>
<button #click="show = !show">Click me</button>
<div :class="`anim-block ${show && 'open'}`">
<div class="content">
<p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Eaque
beatae, recusandae laborum nihil, natus placeat aut facere reiciendis
esse cumque dicta quas possimus qui maxime asperiores sed a
repudiandae praesentium.
</p>
</div>
</div>
</div>
</template>
CSS:
<style scoped>
.anim-block {
position: relative;
width: 0;
height: 0;
background-color: rgb(194, 209, 223);
opacity: 0;
overflow: hidden;
transition: all 0.3s;
}
.anim-block.open {
width: 280px;
height: 300px;
opacity: 1;
}
.anim-block .content {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 280px;
height: 300px;
padding: 30px auto;
}
.anim-block .content p {
color: rgb(34, 39, 53);
}
</style>
Side note: this is my first post, so sorry if my explanation is unclear. If you have any questions, feel free to ask!

screen.height & screen.width not returning correct values

I am enabling an overlay upon clicking on button, then when user minimizes the screen overlay is not covering full page. User able to click on buttons when minimizes the screen.
I am setting the screen.height & screen.width to overlay div. But upon minimizes to certain level again buttons are visible.
id1 is a id of overlay division
document.getElementById("id1").style.height=screen.height;
document.getElementById("id1").style.width=screen.width;
i want overlay to display over complete web page
Ok, Here is what we do to create Overlays..
You should have a parent div like
<div class="body_wrapper">
<div class="overlay"></div>
<div class="page_content">
<-- You Page Content -->
</div>
</div>
Here inside <body> tag you got a body_wrapper and inside that you got overlay and page__content. Now in your style sheet:
.body_wrapper {
position: relative;
}
.overlay {
position: absolute;
right: 0;
top: 0;
left: 0;
bottom: 0;
background: rgba(0,0,0,0.5);
}
The screen.height doesn't always return the valid screen height,
check this for more information.
Your task can be achieved by CSS and a little bit of JavaScript.
The CSS has two units that are likely the keys to your issue : the vw and the vh units. Check this MDN article for more information.
So, here's a demo that shows how you can achieve your task by the help of CSS and some JavaScript for the event handling.
let trigger = document.getElementById('trigger'),
triggersClose = document.querySelectorAll('.trigger-close'),
fullScreen = document.getElementById('fullscreen');
/** click event listener for the button to show the overlay **/
trigger.addEventListener('click', e => {
e.preventDefault();
fullScreen.classList.add('visible'); /** add .visible class so the overlay is shown **/
});
/** cycle through the buttons that can hide the overlay and add a click event for them **/
triggersClose.forEach(el => {
el.addEventListener('click', e => {
e.preventDefault();
fullScreen.classList.remove('visible'); /** remove .visible class so the overlay becomes hidden **/
});
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.overlay {
display: none; /** the overlay is initially hidden **/
position: fixed; /** stays on the same place even when scrolling in the background **/
width: 100vw; /** vw : viewport width = 1% of the viewport's width. It changes accordingly when zooming (responsive) **/
height: 100vh; /** vh : viewport height = 1% of the viewport's height. It changes accordingly when zooming (responsive) **/
top: 0;
left: 0;
justify-content: center; /** center the content horizontally **/
align-items: center; /** center the content vertically **/
padding: 15px;
background: rgba(24, 24, 24, .6);
z-index: 999; /** stays on top **/
}
.overlay.visible {
/** this class is used by JavaScript to show the overlay **/
display: flex; /** flex makes our life easier ! **/
}
.overlay .overlay-wrapper {
display: flex;
flex-direction: column;
width: 65%;
max-height: 100%;
overflow-y: auto; /** adds scrollbars when the content is too much **/
background-color: #fff;
}
.overlay .overlay-wrapper .overlay-header {
position: relative;
background-color: #1548a6;
}
.overlay .overlay-wrapper .overlay-header>.text,
.overlay .overlay-wrapper .overlay-body {
padding: 15px 5px;
}
.overlay .overlay-wrapper .overlay-header>.trigger-close {
position: absolute;
width: 45px;
right: 0;
top: 0;
bottom: 0;
margin: auto;
font-size: 1.1rem;
font-weight: bold;
border: 0;
color: #fff;
background-color: #dc3545;
cursor: pointer;
border-top-right-radius: 4px
}
.overlay .overlay-wrapper .overlay-footer>.trigger-close {
float: right;
margin-bottom: 5px;
margin-right: 5px;
padding: 8px 15px;
color: #fff;
background-color: #007bff;
border: 0;
border-radius: 4px;
}
<button id="trigger">click me !</button>
<div id="fullscreen" class="overlay">
<div class="overlay-wrapper">
<div class="overlay-header">
<h3 class="text">Message heading</h3>
<button class="trigger-close">×</button>
</div>
<div class="overlay-body">
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. In facere fugiat aperiam officiis debitis voluptas soluta assumenda cumque reiciendis blanditiis nostrum, consequuntur vero corporis doloribus! Expedita voluptatem illum maiores culpa.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Beatae ex temporibus, possimus commodi, obcaecati nostrum maiores cupiditate voluptas voluptate unde qui quasi accusantium earum dolores pariatur fuga. Optio, officia praesentium.</p>
</div>
<div class="overlay-footer"><button class="trigger-close">close</button></div>
</div>
</div>
Learn more about flexbox (display: flex).
Hope I pushed you further.

Sidebar together with Skeleton CSS

I am trying to place a sidebar right next to the 960px wide Skeleton container. I have successfully done that, but I am looking for a better way to do that, while keeping the container centered on the screen.
https://jsfiddle.net/dgujg9xb/
aside {
width: 250px;
float: left;
margin-left: -170px;
}
By giving it a negative margin, I can float it outside the container it is inside (#holder). However, that is extremely bad and doesn't work that well. By resizing the screen, I want the sidebar to cut so it sits on top instead (like on a phone using media queries), but that seems impossible this way.
Is there a better way to structure this? I am willing to use a JavaScript library as long as it works very well.
I've made a Codepen of something that may be of use, you can alter the content and styling in there and see. The content container has a fixed width, then collapses when things don't fit neatly. I've also popped in the Sass and HTML here. This should just be an example of how it could be achieved, in the real thing you're probably better off using percentages for obvious responsivity reasons.
http://codepen.io/BlitZ_UK/pen/GrEExr
The styling is done in Sass;
.page-container {
background: #607D8B;
min-height: 100vh;
}
.content {
padding: 10px 20px
}
.sidebar {
background: #009688;
}
.inner-wrapper {
background: #00bcd4;
margin: 0 auto;
max-width: 960px;
position: relative;
}
#media all and (min-width: 1362px) {
.sidebar {
width: 200px;
position: absolute;
left: 0;
transform: translateX(-100%);
}
}
And the HTML;
<div class="page-container">
<div class="inner-wrapper">
<div class="sidebar">
<ol>
<li>Lorem ipsum dolor.</li>
<li>Lorem ipsum dolor.</li>
<li>Lorem ipsum dolor.</li>
</ol>
</div>
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Deserunt facere expedita voluptatem reprehenderit, asperiores architecto magni laborum repellat perferendis voluptas alias autem cumque iste dignissimos ab officiis totam blanditiis ratione.</p>
</div>
</div>
</div>
Hope it helped.
Make the sidebar absolute and place it independent and above with z-index from the rest of the layout.
Note I commented 960px width from #holder just for demonstration (since snippet viewport is smaller it would overflow otherwise), also added sidebar jQuery toggle for the same purpose.
Your fiddle:
My fiddle:
External Fiddle if you wish to resize
Snippet below:
$(".container").on("click", function() {
$("aside").toggleClass("showAside");
});
* {
box-sizing: border-box;
}
html,
body {
width: 100%;
height: 100%;
}
#holder {
/* width: 960px; */
position: relative;
margin: 0 auto;
height: 100%;
}
aside {
width: 250px;
background: black;
color: white;
position: absolute;
top: 0;
left: -170px;
z-index: 1;
transition: all .4s ease-in;
}
.showAside {
left: 0;
}
.container {
border: 1px solid black;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/skeleton/2.0.4/skeleton.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="holder">
<aside>
Sidebar goes here
</aside>
<div class="container">
Hello - click to show/hide sidebar
</div>
</div>

Categories