I have a list of team members. Each member element consists of an image cropped in a circle inside white box. When you hover on the box, the image changes to fullsize. It was inspired by this website:
I achieve this same animation with SVGs. However, in the website above, each image is exactly 300X350 - the same size as the white container box. This creates a flawless transition from masked image to fullsize image - nothing appears to jump or move. On the other hand, my images are a variety of sizes. As a result, the visible portion of the SVG is either zoomed in or out the image, and when you hover, the full image appears to jump:
How can I get the scale and size of fullsize image to match that in the SVG view box, such that it doesn't appear to move?
JSFiddle: http://jsfiddle.net/mzechar/afnxkt2h/2/
html:
<li>
<a href="#">
<article>
<div>
<!-- The masked image -->
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100">
<defs>
<clipPath id="circle">
<circle cx="50" cy="50" r="35"/>
</clipPath>
</defs>
<image width="100%" height="100%" preserveAspectRatio="xMinYMin slice" xlink:href="team/finishedBW/CCK.jpg__.jpg" clip-path="url(#circle)"/>
</svg>
</div>
<!-- The full revealed image -->
<img class="img-full" src="team/finishedBW/CCK.jpg__.jpg" alt="">
<!-- The circle ring -->
<svg viewBox="0 0 100 100" class="circle-ring">
<circle cx="50" cy="50" r="35" stroke="white" stroke-width=".5" fill="transparent" />
</svg>
<div class="bio">
<h2>Chun-Kang Chen</h2>
<h4>Article Subtitle</h4>
</div>
</article>
</a>
</li>
<li>
CSS:
.team-listing{
position:relative;
margin-top:40px;
margin-right:auto;
margin-left:auto;
}
.team-listing li{
display:inline-block;
overflow: hidden;
float:left;
height: 340px;
list-style-position:inside;
margin: 1px 1px 1px 1px;
background-color:#fff;
}
.team-listing ul{
display: flex;
flex-wrap: wrap;
justify-content: center;
flex-direction: row;
flex-flow: row wrap;
flex-shrink: 1;
flex-grow: 1;
float: left;
min-width: 0;
max-width: 100%;
position: relative;
filter: drop-shadow(5px 5px 5px rgba(2,2,22,0.1));
}
a {
display: inline-block;
}
article {
position: relative;
width: 300px;
height: 350px;
/* prevent scaled circle ring from triggering hover */
overflow: hidden;
}
/* create the colour overlay */
article:after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: none;
background: rgba(0, 255, 255, .2);
z-index: 3;
}
/* place full image above SVG */
.img-full {
position: absolute;
top: 0;
right:0;
z-index: 2;
/* hide the full image initially */
display: none;
}
.circle-ring {
position: absolute;
top: 0;
z-index: 3;
/* initially hidden with opacity so it can be animated */
opacity: 0;
transform-origin: 50% 50%;
transform: scale(1.8);
transition: transform .3s ease, opacity .4s ease;
}
a:hover .img-full,
a:hover article:after {
position:absolute;
display: block;
}
a:hover .circle-ring {
opacity: 1;
transform: scale(1);
}
.bio {
position: absolute;
bottom: 0;
padding: 1rem 2rem;
color: #000;
/* keep text above SVG, full image and overlay */
z-index: 4;
}
a:hover .bio {
color: #FFF;
}
/* general */
h2,
h4 {
margin: 0;
font-family: sans-serif;
}
h4 {
font-weight: 300;
}
Have confidence in SVG content. There is no need to define two <svg> elements and a HTML <img> inbetween. Just position the image in an <image> tag inside one <svg> parent, and set/remove the clip path depending on hover state.
The clip path itself remains in a separate, but hidden <svg> so it can be reused for multiple images.
If both the image dimensions and their position so they show the right clipped content differ, it is probably better not to depend on preserveAspectRatio, but to set them absolutely. (Setting overflow:hidden on the <svg> element is more of a precaution, since the spec has changed a bit whether that is the default.)
a {
display: inline-block;
}
article {
position: relative;
width: 300px;
height: 350px;
overflow: hidden;
}
article::after {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
display: none;
background: rgba(0, 255, 255, .2);
z-index: 3;
}
.portrait {
position: relative;
width: 300px;
height: 300px;
overflow: hidden;
}
.portrait image {
clip-path: url(#circle);
}
a:hover .portrait image {
clip-path: none;
}
a:hover article:after {
position: absolute;
display: block;
}
.ring {
fill: none;
stroke: white;
stroke-width: 1;
opacity: 0;
transform-origin: 50% 50%;
transform: scale(1.8);
transition: transform .3s ease, opacity .4s ease;
}
a:hover .ring {
opacity: 1;
transform: scale(1);
}
.bio {
position: absolute;
bottom: 0;
padding: 1rem 2rem;
color: #000;
}
h2 {
font-size: 1.5em;
font-weight: bold;
}
h4 {
font-weight: 300;
}
h2, h4 {
margin: 0;
font-family: sans-serif;
}
<svg width="0" height="0">
<clipPath id="circle">
<circle cx="150" cy="150" r="100"/>
</clipPath>
</svg>
<a href="#">
<article>
<svg class="portrait" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 300 300">
<!-- no automatic sizing for SVG image, width and height must be set -->
<image width="400" height="300" x="-100" y="0"
xlink:href="http://api.leafsnap.com/v1/team/images/columbia/Neeraj.jpg?h=300"/>
<circle class="ring" cx="150" cy="150" r="100" />
</svg>
<div class="bio">
<h2>Chun-Kang Chen</h2>
<h4>Article Subtitle</h4>
</div>
</article>
</a>
Crop your images, throw out those useless tags and use every image only once.
Hope this helps:
section.team {
margin: auto;
background: #fefefe;
}
.team-listing {
position: relative;
margin: 40px auto 0;
display: flex;
filter: drop-shadow(5px 5px 5px rgba(2, 2, 22, 0.1));
}
.team-listing li {
overflow: hidden;
height: 350px;
list-style: none;
margin: 1px;
background-color: #fff;
}
article {
position: relative;
top: 0;
width: 300px;
height: 300px;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.img-full {
-webkit-clip-path: circle(30% at 50% 50%);
clip-path: circle(30% at 50% 50%);
width: 500px;
}
a:hover .img-full {
-webkit-clip-path: none;
clip-path: none;
filter: sepia(100%);
}
.circle-ring {
position: absolute;
top: 0;
z-index: 3;
opacity: 0;
transform-origin: 50% 50%;
transform: scale(1.8);
transition: transform 0.3s ease, opacity 0.4s ease;
}
a:hover .circle-ring {
opacity: 1;
transform: scale(1);
}
.bio {
position: absolute;
bottom: 0;
margin: 2rem;
color: #000;
}
a:hover .bio > h2 {
color: #fff;
}
h2,
h4 {
margin: 0;
font-family: sans-serif;
}
h4 {
font-weight: 300;
}
<section class="content-wrapper team">
<ul class="team-listing">
<li>
<a href="#">
<article>
<img class="img-full" src="https://i.imgur.com/6eRLJ4I.jpg" alt="">
<svg viewBox="0 0 100 100" class="circle-ring">
<circle cx="50" cy="50" r="35" stroke="white" stroke-width=".5" fill="transparent" />
</svg>
</article>
<div class="bio">
<h2>Article Title</h2>
<h4>Article Subtitle</h4>
</div>
</a>
</li>
<li>
<a href="#">
<article>
<img class="img-full" src="https://i.imgur.com/6eRLJ4I.jpg" alt="">
<svg viewBox="0 0 100 100" class="circle-ring">
<circle cx="50" cy="50" r="35" stroke="white" stroke-width=".5" fill="transparent" />
</svg>
</article>
<div class="bio">
<h2>Article Title</h2>
<h4>Article Subtitle</h4>
</div>
</a>
</li>
</ul>
</section>
Related
I'm trying to put some buttons on my site, but I'm struggling with positioning some of the animated elements. See the example:
https://codepen.io/dev_loop/pen/MWKYoGJ
<div class="btn-container">
<button>
<span class="text">Hover1</span>
<div class="icon-container">
<div class="icon icon--left">
<svg>
<use xlink:href="#arrow-right"></use>
</svg>
</div>
<div class="icon icon--right">
<svg>
<use xlink:href="#arrow-right"></use>
</svg>
</div>
</div>
</button>
</div>
<div class="btn-container">
<button>
<span class="text">Hover2Test</span>
<div class="icon-container">
<div class="icon icon--left">
<svg>
<use xlink:href="#arrow-right"></use>
</svg>
</div>
<div class="icon icon--right">
<svg>
<use xlink:href="#arrow-right"></use>
</svg>
</div>
</div>
</button>
</div>
<svg style="display: none;">
<symbol id="arrow-right" viewBox="0 0 20 10">
<path d="M14.84 0l-1.08 1.06 3.3 3.2H0v1.49h17.05l-3.3 3.2L14.84 10 20 5l-5.16-5z"></path>
</symbol>
</svg>
<div class="support">
<i class="fab fa-twitter-square"></i>
<i class="fab fa-dribbble"></i>
</div>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
width: 100%;
height: 100vh;
display: flex;
overflow: hidden;
}
.btn-container {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
background: var(--bg);
&:nth-child(1) {
--btn-bg: #da0000;
--bg: #f22c3a;
}
&:nth-child(2) {
--btn-bg: #fac300;
--bg: #fc6100;
}
}
button {
--width: 180px;
--height: 60px;
border: 0;
position: relative;
min-width: var(--width);
min-height: var(--height);
border-radius: var(--height);
color: #fff;
font-family: "Montserrat";
font-weight: bold;
background: rgba(0, 0, 0, 0.3);
cursor: pointer;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
margin: 0 1rem;
.text,
.icon-container {
position: relative;
z-index: 2;
}
.icon-container {
--icon-size: 25px;
position: relative;
width: var(--icon-size);
height: var(--icon-size);
margin-left: 15px;
transition: transform 500ms ease;
.icon {
position: absolute;
left: 0;
top: 0;
width: var(--icon-size);
height: var(--icon-size);
transition: transform 500ms ease, opacity 250ms ease;
&--left {
transform: translateX(-200%);
opacity: 0;
}
svg {
width: 100%;
height: 100%;
fill: #fff;
}
}
}
&::after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: var(--btn-bg);
border-radius: var(--height);
z-index: 1;
transition: transform 500ms ease;
}
&:hover {
&::after {
transform: translateX(65%);
}
.icon-container {
transform: translateX(125%);
.icon {
&--left {
transform: translateX(0);
opacity: 1;
}
&--right {
transform: translateX(200%);
opacity: 0;
}
}
}
}
}
.support{
position: absolute;
right: 10px;
bottom: 10px;
padding: 10px;
display: flex;
a{
margin: 0 10px;
color: #fff;
font-size: 1.8rem;
backface-visibility: hidden;
transition: all 150ms ease;
&:hover{
transform: scale(1.1);
}
}
}
In the above, everything works perfectly until you change the text contained within the button itself. Doing this throws off the "hover" positioning of the SVG arrow element, since its parent containers position is decided by the text on the button and its a percentage based translateX.
I want to use this code across multiple buttons with different text on each button and I'm looking to implement something on the transition effects like:
"Move the SVG from whatever its current position is, to right:0; or so when hovered, so the arrow is essentially right aligned"
What I've ended up doing in my code, is creating two different containers for the SVG; One positioned relatively in the "left" position, and another positioned absolute with a right:18px property to "stick" it to the right hand side of the button. I've then animated the opacity and translateX to try and make it look like its following the wipe effect of the button, but it's not really working nicely and looks janky.
https://codepen.io/Delarado/pen/yLqOBRr
<div class="btn-container">
<button>
<span class="text">Reset</span>
<div class="icon-container icon-container--left">
<div class="icon">
<svg>
<use xlink:href="#arrow-right"></use>
</svg>
</div>
</div>
<div class="icon-container icon-container--right">
<div class="icon">
<svg>
<use xlink:href="#arrow-right"></use>
</svg>
</div>
</div>
</button>
</div>
<svg style="display: none;">
<symbol id="arrow-right" viewBox="0 0 20 10">
<path d="M14.84 0l-1.08 1.06 3.3 3.2H0v1.49h17.05l-3.3 3.2L14.84 10 20 5l-5.16-5z"></path>
</symbol>
</svg>
.btn-container {
width: 100%;
height: 100%;
margin: 1em 0;
display: flex;
justify-content: center;
align-items: center;
background: var(--bg);
--btn-bg: #ff9900;
}
button {
--width: 13em;
--height: 60px;
border: 0;
position: relative;
min-width: var(--width);
min-height: var(--height);
border-radius: var(--height);
color: #fff;
font-weight: bold;
font-size: 1.1rem;
background: #ff990075;
cursor: pointer;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
margin: 0 1rem;
border-color: #00000050;
border-width: 1px;
border-style: solid;
.text,
.icon-container {
position: relative;
z-index: 2;
}
.icon-container {
--icon-size: 25px;
position: relative;
width: var(--icon-size);
height: var(--icon-size);
margin-left: 10px;
transition: transform 500ms ease;
.icon {
position: absolute;
left: 0;
top: 0;
width: var(--icon-size);
height: var(--icon-size);
transition: transform 500ms ease, opacity 250ms ease;
svg {
width: 100%;
height: 100%;
fill: #fff;
}
}
&--right {
//transform: translateX(-200%);
display:none;
}
}
&::after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: var(--btn-bg);
border-radius: var(--height);
z-index: 1;
transition: transform 500ms ease;
}
&:hover {
//The color of the text upon hovering
color: #000;
&::after {
//The position of the circle upon hovering
transform: translateX(73%);
}
.icon-container {
// //The position of the arrow upon hovering
// //transform: translateX(25%);
&--left {
opacity: 0;
animation: Arrowgo 500ms forwards;
}
&--right {
position: absolute;
right:18px;
display:unset;
animation: Arrowarrive 500ms forwards;
}
}
}
}
#keyframes Arrowgo {
from{
opacity:1;
transform: translateX(0);
}
to{
opacity:0;
transform:translateX(20px);
}
}
#keyframes Arrowarrive {
from{
opacity:0;
transform: translateX(-20px);
}
to{
opacity:1;
transform:translateX(0);
}
}
I also tried a single element with relative position, animated to absolute position on hover but that also looked awful. I can't figure out how to place it just to the right of the button text in a normal state, and then animate it from there over to the right hand side on hover.
I was wondering if anyone smarter than me had a nice elegant solution to this that avoids having a different class for each button to account for the different length text, whilst still maintaining a nice slick wipe effect on both the "secondary" button and the arrow SVG?
Thanks in advance!
I have this structure and it works perfectly only in chrome!!:
.audio-controls {
display: none;
flex-direction: row;
gap: 1226px;
justify-content: center;
width: 100%;
position: absolute;
top: 82%;
left: 0%;
z-index: 99;
}
.prompt {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: not-allowed;
background: #000000;
border-radius: 35px;
}
.prompt .stim {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 124px;
width: 126px;
border-radius: 30%;
background: linear-gradient(#1f1f20, #040404);
transform: translateY(-6px);
overflow: hidden;
box-shadow: 0px 9px 3px #000000, 0 10px 20px rgb(0 0 0 / 25%);
}
.prompt .stim::before {
content: "";
opacity: 0.35;
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
background-image: url(../img/hexellence.png);
}
.audio-controls .record {
transform: translate(0px, 40px);
zoom: 0.042;
}
.prompt .stim p {
transition: color 0.05s ease;
}
.stim p {
color: #b9b7b7;
font-family: "Open Sans Regular";
font-size: .7em;
margin-bottom: 4px;
transition: color 0.1s ease-in-out;
z-index: 1;
}
<div class="audio-controls" style="display: flex;">
<div id="start-recognition" class="prompt activated">
<div class="record-dot record-dot-position on" style="transform: translateY(-6px);"></div>
<div class="record-dot-container record-dot-position" style="transform: translateY(-6px);"></div>
<div class="stim">
<svg class="record" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" enable-background="new 0 0 1000 1000" xml:space="preserve" style="fill: rgb(123, 55, 32);" width="1000" height="1000">
<rect id="backgroundrect" width="100%" height="100%" x="0" y="0" fill="none" stroke="none"></rect>
<g class="currentLayer" style="">
<g id="svg_1" class="selected" fill="#dadada" fill-opacity="1">
<path d="M500,683.8c84.6,0,153.1-68.6,153.1-153.1V163.1C653.1,78.6,584.6,10,500,10c-84.6,0-153.1,68.6-153.1,153.1v367.5C346.9,615.2,415.4,683.8,500,683.8z M714.4,438.8v91.9C714.4,649,618.4,745,500,745c-118.4,0-214.4-96-214.4-214.4v-91.9h-61.3v91.9c0,141.9,107.2,258.7,245,273.9v124.2H346.9V990h306.3v-61.3H530.6V804.5c137.8-15.2,245-132.1,245-273.9v-91.9H714.4z" id="record-icon" fill="#dadada57" style="fill: rgba(218, 218, 218, 0.34);"></path>
</g>
</g>
</svg>
<p id="record-icon-text" style="color: rgb(185, 183, 183);">Hold Space Key</p>
</div>
</div>
</div>
The issue is in the above code I used zoom here:
.audio-controls .record {
transform: translate(0px, 40px);
zoom: 0.042;
}
And zoom is not working in Firefox so it only works in chrome.
In order to make this work I need to use scale instead right? I used scale in the below snippet but I ruined the graphic !
Have a look: ( I only removed zoom and replaces scale here)
.audio-controls {
display: none;
flex-direction: row;
gap: 1226px;
justify-content: center;
width: 100%;
position: absolute;
top: 82%;
left: 0%;
z-index: 99;
}
.prompt {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
cursor: not-allowed;
background: #000000;
border-radius: 35px;
}
.prompt .stim {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 124px;
width: 126px;
border-radius: 30%;
background: linear-gradient(#1f1f20, #040404);
transform: translateY(-6px);
overflow: hidden;
box-shadow: 0px 9px 3px #000000, 0 10px 20px rgb(0 0 0 / 25%);
}
.prompt .stim::before {
content: "";
opacity: 0.35;
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
background-image: url(../img/hexellence.png);
}
.audio-controls .record {
transform: scale(0.042) translate(0px, 40px);
/*zoom: 0.042;*/
}
.prompt .stim p {
transition: color 0.05s ease;
}
.stim p {
color: #b9b7b7;
font-family: "Open Sans Regular";
font-size: .7em;
margin-bottom: 4px;
transition: color 0.1s ease-in-out;
z-index: 1;
}
<div class="audio-controls" style="display: flex;">
<div id="start-recognition" class="prompt activated">
<div class="record-dot record-dot-position on" style="transform: translateY(-6px);"></div>
<div class="record-dot-container record-dot-position" style="transform: translateY(-6px);"></div>
<div class="stim">
<svg class="record" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" enable-background="new 0 0 1000 1000" xml:space="preserve" style="fill: rgb(123, 55, 32);" width="1000" height="1000">
<rect id="backgroundrect" width="100%" height="100%" x="0" y="0" fill="none" stroke="none"></rect>
<g class="currentLayer" style="">
<g id="svg_1" class="selected" fill="#dadada" fill-opacity="1">
<path d="M500,683.8c84.6,0,153.1-68.6,153.1-153.1V163.1C653.1,78.6,584.6,10,500,10c-84.6,0-153.1,68.6-153.1,153.1v367.5C346.9,615.2,415.4,683.8,500,683.8z M714.4,438.8v91.9C714.4,649,618.4,745,500,745c-118.4,0-214.4-96-214.4-214.4v-91.9h-61.3v91.9c0,141.9,107.2,258.7,245,273.9v124.2H346.9V990h306.3v-61.3H530.6V804.5c137.8-15.2,245-132.1,245-273.9v-91.9H714.4z" id="record-icon" fill="#dadada57" style="fill: rgba(218, 218, 218, 0.34);"></path>
</g>
</g>
</svg>
<p id="record-icon-text" style="color: rgb(185, 183, 183);">Hold Space Key</p>
</div>
</div>
</div>
How can I fix using scale ?
How do I shift the content over to the next row when browser width is 915px?
This is what I have now:
<div class="body">
<div class="container">
<div class="card">
<div class="box">
<div class="percent">
<svg>
<circle cx="70" cy="70" r="70"></circle>
<circle cx="70" cy="70" r="70"></circle>
</svg>
<div class="number">
<h2>90<span>%</span></h2>
</div>
</div>
<h2 class="text">Html</h2>
</div>
</div>
<div class="card">
<div class="box">
<div class="percent">
<svg>
<circle cx="70" cy="70" r="70"></circle>
<circle cx="70" cy="70" r="70"></circle>
</svg>
<div class="number">
<h2>85<span>%</span></h2>
</div>
</div>
<h2 class="text">CSS</h2>
</div>
</div>
<div class="card">
<div class="box">
<div class="percent">
<svg>
<circle cx="70" cy="70" r="70"></circle>
<circle cx="70" cy="70" r="70"></circle>
</svg>
<div class="number">
<h2>60<span>%</span></h2>
</div>
</div>
<h2 class="text">Javascript</h2>
</div>
</div>
</div>
</div>
And my css
.body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
display: flex;
justify-content: space-around;
}
.container .card {
margin-left: 20px;
position: relative;
width: 250px;
background: #222;
background: linear-gradient(0deg, #1b1b1b, #222, #1b1b1b);
display: flex;
justify-content: center;
align-items: center;
height: 300px;
border-radius: 4px;
text-align: center;
overflow: hidden;
transition: 0.5s;
}
.container .card:hover {
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);
transform: translateY(-10px);
}
.container .card:before {
content: "";
position: absolute;
top: 0;
left: -50%;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.03);
pointer-events: none;
z-index: 1;
}
.percent {
position: relative;
width: 150px;
height: 150px;
border-radius: 50%;
box-shadow: inset 0 0 50px #000;
background: #222;
z-index: 100;
}
.percent .number {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
.percent .number h2 {
color: #777;
font-weight: 700;
font-size: 40px;
transition: 0.5s;
}
.card:hover .percent .number h2 {
color: #fff;
font-size: 60px;
}
.percent .number h2 span {
font-size: 24px;
color: #777;
}
.text {
color: #777;
margin-top: 20px;
font-weight: 700;
font-size: 18px;
letter-spacing: 1px;
text-transform: uppercase;
transition: 0.5s;
}
.card:hover .text {
color: #fff;
}
svg {
position: relative;
width: 150px;
height: 150px;
z-index: 1000;
}
circle {
width: 100%;
height: 100%;
fill: none;
stroke: #191919;
stroke-width: 10;
stroke-linecap: round;
transform: translate(5px, 5px);
}
circle:nth-child(2) {
stroke-dasharray: 440;
stroke-dashoffset: 440;
}
.card:nth-child(1) svg circle:nth-child(2) {
stroke-dashoffset: calc(440 - (440 * 90) / 100);
stroke: #00ff43;
}
.card:nth-child(2) svg circle:nth-child(2) {
stroke-dashoffset: calc(440 - (440 * 85) / 100);
stroke: #00a1ff;
}
.card:nth-child(3) svg circle:nth-child(2) {
stroke-dashoffset: calc(440 - (440 * 60) / 100);
stroke: #c104ff;
}
#media only screen and (max-width: 915px) {
/* your css of 1024 px screen size */
.card {
flex: 10% !important;
}
}
How do I make the content shift downwards when on 915px browser width so it looks good on mobile. I've tried flex, change display, change width but nothing works. I don't know if it has to do with any of that but I'd appreciate the help.
You can use the grid layout. First, set the container to display: grid;. After you can set how your grid will be with the grid-template-columns: 1fr; (1fr = one column, 1fr 1fr = 2 column, 1fr 2fr = 2 column, but the right one is bigger... etc). After that, you can add gap: 1rem; to have a gap between you column and row.
The Grid Documentation on W3School
Here is a example:
.body {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.container {
display: flex;
justify-content: space-around;
}
.container .card {
margin-left: 20px;
position: relative;
width: 250px;
background: #222;
background: linear-gradient(0deg, #1b1b1b, #222, #1b1b1b);
display: flex;
justify-content: center;
align-items: center;
height: 300px;
border-radius: 4px;
text-align: center;
overflow: hidden;
transition: 0.5s;
}
.container .card:hover {
box-shadow: 0 15px 35px rgba(0, 0, 0, 0.5);
transform: translateY(-10px);
}
.container .card:before {
content: "";
position: absolute;
top: 0;
left: -50%;
width: 100%;
height: 100%;
background: rgba(255, 255, 255, 0.03);
pointer-events: none;
z-index: 1;
}
.percent {
position: relative;
width: 150px;
height: 150px;
border-radius: 50%;
box-shadow: inset 0 0 50px #000;
background: #222;
z-index: 100;
}
.percent .number {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
border-radius: 50%;
}
.percent .number h2 {
color: #777;
font-weight: 700;
font-size: 40px;
transition: 0.5s;
}
.card:hover .percent .number h2 {
color: #fff;
font-size: 60px;
}
.percent .number h2 span {
font-size: 24px;
color: #777;
}
.text {
color: #777;
margin-top: 20px;
font-weight: 700;
font-size: 18px;
letter-spacing: 1px;
text-transform: uppercase;
transition: 0.5s;
}
.card:hover .text {
color: #fff;
}
svg {
position: relative;
width: 150px;
height: 150px;
z-index: 1000;
}
circle {
width: 100%;
height: 100%;
fill: none;
stroke: #191919;
stroke-width: 10;
stroke-linecap: round;
transform: translate(5px, 5px);
}
circle:nth-child(2) {
stroke-dasharray: 440;
stroke-dashoffset: 440;
}
.card:nth-child(1) svg circle:nth-child(2) {
stroke-dashoffset: calc(440 - (440 * 90) / 100);
stroke: #00ff43;
}
.card:nth-child(2) svg circle:nth-child(2) {
stroke-dashoffset: calc(440 - (440 * 85) / 100);
stroke: #00a1ff;
}
.card:nth-child(3) svg circle:nth-child(2) {
stroke-dashoffset: calc(440 - (440 * 60) / 100);
stroke: #c104ff;
}
#media only screen and (max-width: 915px) {
/* your css of 1024 px screen size */
.card {
flex: 10% !important;
}
.grid-class{
display: grid;
grid-template-columns: 1fr;
gap: 1rem;
}
}
<div class="body">
<div class="container grid-class">
<div class="card">
<div class="box">
<div class="percent">
<svg>
<circle cx="70" cy="70" r="70"></circle>
<circle cx="70" cy="70" r="70"></circle>
</svg>
<div class="number">
<h2>90<span>%</span></h2>
</div>
</div>
<h2 class="text">Html</h2>
</div>
</div>
<div class="card">
<div class="box">
<div class="percent">
<svg>
<circle cx="70" cy="70" r="70"></circle>
<circle cx="70" cy="70" r="70"></circle>
</svg>
<div class="number">
<h2>85<span>%</span></h2>
</div>
</div>
<h2 class="text">CSS</h2>
</div>
</div>
<div class="card">
<div class="box">
<div class="percent">
<svg>
<circle cx="70" cy="70" r="70"></circle>
<circle cx="70" cy="70" r="70"></circle>
</svg>
<div class="number">
<h2>60<span>%</span></h2>
</div>
</div>
<h2 class="text">Javascript</h2>
</div>
</div>
</div>
</div>
I'm looking to create the following setup for a navigation structure.
I'm able to get the white down triangle working without an issue but how do I place yet another triangle (green lines) over the top of the first one without a full border/background or using an image? I can only get a solid green arrow over the white one and that's not what I want to do.
This is what I currently have.
.custom-nav li a:after {
content: "";
z-index: 99;
width: 0;
height: 0;
border-style: solid;
border-width: 40px 150px 0 150px;
border-color: #ffffff transparent transparent transparent;
position: absolute;
top: 173%; left: -75px;
}
<div>
<ul class="custom-nav">
<li>Environment</li>
<li>Health</li>
</ul>
</div>
I think the best option to get something like that is to use an SVG:
body {
margin: 0;
background: #DEE;
}
.nav {
display: flex;
}
.button {
position: relative;
background: transparent;
border: 0;
width: 50%;
height: 100px;
padding: 0 0 50px;
background: content-box white;
font-family: monospace;
font-weight: bold;
outline: none;
cursor: pointer;
}
.button__text {
position: relative;
z-index: 1;
}
.button__triangle {
position: absolute;
top: 25px;
bottom: 0;
left: 50%;
width: 100%;
transition: transform ease-in 150ms;
transform: translate(-50%, -50%);
}
.button:hover > .button__triangle {
transform: translate(-50%, 0);
}
.button__triangle--big {
fill: white;
}
.button__triangle--small {
fill: white;
stroke: red;
stroke-width: 2px;
stroke-linecap: round;
opacity: 0;
transition: opacity ease-in 150ms;
}
.button:hover .button__triangle--small {
opacity: 1;
}
<nav class="nav">
<button class="button">
<span class="button__text">OPTION 1</span>
<svg viewBox="0 0 200 50" class="button__triangle">
<polygon points="0,0 100,50 200,0" class="button__triangle--big" />
<polyline points="50,5 100,30 150,5" class="button__triangle--small" />
</svg>
</button>
<button class="button">
<span class="button__text">OPTION 2</span>
<svg viewBox="0 0 200 50" class="button__triangle">
<polygon points="0,0 100,50 200,0" class="button__triangle--big" />
<polyline points="50,5 100,30 150,5" class="button__triangle--small" />
</svg>
</button>
</nav>
Multiple background can do this:
.box {
--w:160px; /* width of the arrow */
--h:40px; /* height of the arrow*/
--b:2px; /* thickness of the green arrow */
--o:20%; /* offset of the green arrow */
/* gadient coloration, white then the green border then white again then transparent */
--g:#fff var(--o),
green var(--o) calc(var(--o) + var(--b)),
#fff calc(var(--o) + var(--b) + 1px) 49.8%,
transparent 50%;
height:50px;
margin:5px;
border-bottom:var(--h) solid transparent; /* the arrow will take the border space */
background:
linear-gradient(to bottom right,var(--g)) calc(50% + calc(var(--w)/4)) 100% border-box,
linear-gradient(to bottom left ,var(--g)) calc(50% - calc(var(--w)/4)) 100% border-box,
#fff padding-box;
background-size:calc(var(--w)/2) var(--h);
background-repeat:no-repeat;
}
body {
background:#000;
}
<div class="box"></div>
<div class="box" style="--w:200px;--h:60px;--o:30%;--b:5px"></div>
<div class="box" style="--w:180px;--h:30px;--o:10%;--b:3px"></div>
I'm starting to using css grid and flex box but I have a problem trying to align this list to the center.
Here is the codepen and snippet:
* {
box-sizing: border-box;
}
.container-shell {
background: gray;
display: -ms-grid;
display: grid;
grid-template-areas: "nav content content";
-ms-grid-columns: 60px 1fr;
grid-template-columns: 60px 1fr;
-ms-grid-rows: auto;
grid-template-rows: auto;
height: 100vh;
}
nav {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: nav;
background-color: #fff;
}
main {
-ms-grid-row: 1;
-ms-grid-column: 2;
-ms-grid-column-span: 2;
grid-area: content;
}
.navigation-container {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.navigation-flex-item {
flex: 1 0 50%;
text-align: center;
padding: 10px;
min-width: 0;
}
ul {
list-style: none;
margin: 0;
}
.--no-padding {
padding: 0 !important;
}
.--bottom {
align-self: flex-end;
}
.navbar-toggle {
margin: 14px 5px 14px 0 !important;
border: 0 !important;
transition: all .1s linear !important;
cursor: pointer;
}
.navbar-toggle {
position: relative;
float: right;
margin-right: 15px;
padding: 9px 10px;
margin-top: 33px;
margin-bottom: 33px;
background-color: transparent;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
}
.sr-only {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rec(0, 0, 0, 0);
border: 0;
}
.icon-bar {
display: block;
width: 22px;
height: 2px;
border-radius: 1px;
background-color: #888;
}
.icon-bar {
width: 30px;
height: 3px;
background-color: #000;
border-radius: 0;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
transition: all .1s linear;
-webkit-transform: rotate(0);
transform: rotate(0);
}
.icon-bar:nth-child(2) {
width: 19px;
margin-left: 11px;
}
.icon-bar + .icon-bar {
margin-top: 4px;
}
.icon-bar:last-of-type {
width: 19px;
margin-right: 11px;
}
<div class="container-shell">
<nav>
<div style="height: 100%">
<div class="navigation-container">
<ul class="navigation-flex-item">
<li>1</li>
<li>2</li>
<li><svg _ngcontent-c2="" xml:space="preserve" xmlns:xlink="http://www.w3.org/1999/xlink" id="Capa_1" style="enable-background:new 0 0 60 60;" version="1.1" viewBox="0 0 60 60" x="0px" xmlns="http://www.w3.org/2000/svg" y="0px">
<g _ngcontent-c2="">
<path _ngcontent-c2="" d="M57,4h-7V1c0-0.553-0.447-1-1-1h-7c-0.553,0-1,0.447-1,1v3H19V1c0-0.553-0.447-1-1-1h-7c-0.553,0-1,0.447-1,1v3H3
C2.447,4,2,4.447,2,5v11v43c0,0.553,0.447,1,1,1h54c0.553,0,1-0.447,1-1V16V5C58,4.447,57.553,4,57,4z M43,2h5v3v3h-5V5V2z M12,2h5
v3v3h-5V5V2z M4,6h6v3c0,0.553,0.447,1,1,1h7c0.553,0,1-0.447,1-1V6h22v3c0,0.553,0.447,1,1,1h7c0.553,0,1-0.447,1-1V6h6v9H4V6z
M4,58V17h52v41H4z"></path>
<path _ngcontent-c2="" d="M38,23h-7h-2h-7h-2h-9v9v2v7v2v9h9h2h7h2h7h2h9v-9v-2v-7v-2v-9h-9H38z M31,25h7v7h-7V25z M38,41h-7v-7h7V41z M22,34h7v7h-7
V34z M22,25h7v7h-7V25z M13,25h7v7h-7V25z M13,34h7v7h-7V34z M20,50h-7v-7h7V50z M29,50h-7v-7h7V50z M38,50h-7v-7h7V50z M47,50h-7
v-7h7V50z M47,41h-7v-7h7V41z M47,25v7h-7v-7H47z"></path>
</g><g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
</svg>
</li>
</ul>
<div class="navigation-flex-item --bottom --no-padding">
<button class="navbar-toggle">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
</div>
</div>
</nav>
<main>
Hello World Content!
</main>
</div>
As you can see the hamburger icon aligned to the center which is fine but the text (list) is aligned to the left, how can I center the text and the image without break the hamburger icon. I already tried with align and justify.
Have made the below changes to your code:
The default flex-direction is row - you have to change it to column for the navigation-container.
Remove flex: 1 0 50% from the element navigation-flex-item.
Absolutely position the hamburger to the bottom.
See code below:
* {
box-sizing: border-box;
}
body {
background: blue; /* for illustration */
}
.container-shell {
background: gray;
display: -ms-grid;
display: grid;
grid-template-areas: "nav content content";
-ms-grid-columns: 60px 1fr;
grid-template-columns: 60px 1fr;
-ms-grid-rows: auto;
grid-template-rows: auto;
height: 100vh;
}
nav {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: nav;
background-color: #fff;
}
main {
-ms-grid-row: 1;
-ms-grid-column: 2;
-ms-grid-column-span: 2;
grid-area: content;
}
.navigation-container {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column; /* ADDED */
height: 100%;
}
.navigation-flex-item {
/*flex: 1 0 50%;*/
text-align: center;
padding: 10px;
min-width: 0;
}
ul {
list-style: none;
margin: 0;
}
.--no-padding {
padding: 0 !important;
}
.--bottom {
/*align-self: flex-end;*/
position: absolute; /* ADDED */
bottom: 0; /* ADDED */
}
.navbar-toggle {
margin: 14px 5px 14px 0 !important;
border: 0 !important;
transition: all .1s linear !important;
cursor: pointer;
}
.navbar-toggle {
position: relative;
float: right;
margin-right: 15px;
padding: 9px 10px;
margin-top: 33px;
margin-bottom: 33px;
background-color: transparent;
background-image: none;
border: 1px solid transparent;
border-radius: 4px;
}
.sr-only {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.sr-only {
position: absolute;
width: 1px;
height: 1px;
margin: -1px;
padding: 0;
overflow: hidden;
clip: rec(0, 0, 0, 0);
border: 0;
}
.icon-bar {
display: block;
width: 22px;
height: 2px;
border-radius: 1px;
background-color: #888;
}
.icon-bar {
width: 30px;
height: 3px;
background-color: #000;
border-radius: 0;
-webkit-transform-origin: 50% 50%;
transform-origin: 50% 50%;
transition: all .1s linear;
-webkit-transform: rotate(0);
transform: rotate(0);
}
.icon-bar:nth-child(2) {
width: 19px;
margin-left: 11px;
}
.icon-bar+.icon-bar {
margin-top: 4px;
}
.icon-bar:last-of-type {
width: 19px;
margin-right: 11px;
}
<div class="container-shell">
<nav>
<div style="height: 100%">
<div class="navigation-container">
<ul class="navigation-flex-item">
<li>1</li>
<li>2</li>
<li><svg _ngcontent-c2="" xml:space="preserve" xmlns:xlink="http://www.w3.org/1999/xlink" id="Capa_1" style="enable-background:new 0 0 60 60;" version="1.1" viewBox="0 0 60 60" x="0px" xmlns="http://www.w3.org/2000/svg" y="0px">
<g _ngcontent-c2="">
<path _ngcontent-c2="" d="M57,4h-7V1c0-0.553-0.447-1-1-1h-7c-0.553,0-1,0.447-1,1v3H19V1c0-0.553-0.447-1-1-1h-7c-0.553,0-1,0.447-1,1v3H3
C2.447,4,2,4.447,2,5v11v43c0,0.553,0.447,1,1,1h54c0.553,0,1-0.447,1-1V16V5C58,4.447,57.553,4,57,4z M43,2h5v3v3h-5V5V2z M12,2h5
v3v3h-5V5V2z M4,6h6v3c0,0.553,0.447,1,1,1h7c0.553,0,1-0.447,1-1V6h22v3c0,0.553,0.447,1,1,1h7c0.553,0,1-0.447,1-1V6h6v9H4V6z
M4,58V17h52v41H4z"></path>
<path _ngcontent-c2="" d="M38,23h-7h-2h-7h-2h-9v9v2v7v2v9h9h2h7h2h7h2h9v-9v-2v-7v-2v-9h-9H38z M31,25h7v7h-7V25z M38,41h-7v-7h7V41z M22,34h7v7h-7
V34z M22,25h7v7h-7V25z M13,25h7v7h-7V25z M13,34h7v7h-7V34z M20,50h-7v-7h7V50z M29,50h-7v-7h7V50z M38,50h-7v-7h7V50z M47,50h-7
v-7h7V50z M47,41h-7v-7h7V41z M47,25v7h-7v-7H47z"></path>
</g><g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
<g _ngcontent-c2="">
</g>
</svg>
</li>
</ul>
<div class="navigation-flex-item --bottom --no-padding">
<button class="navbar-toggle">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
</div>
</div>
</nav>
<main>
Hello World Content!
</main>
</div>