I have this situation: https://jsfiddle.net/rozkvsdh/5/
A CSS Grid, simply, but in some items, I need to put a ribbon or another div.
It's impossible!
How can I do?
grid-item {
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
}
.ribbon-wrapper {
width: 85px; // the length should be not in px I think!
height: 88px; // the length should be not in px I think!
overflow: hidden;
//position: absolute; it doesn't work!
position: relative;
top: -3px;
left: -3px;
.ribbon {
font: bold 15px sans-serif;
color: #333;
text-align: center;
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
position: relative;
padding: 7px 0;
top: 15px;
left: -30px;
width: 120px;
background-color: #ebb134;
color: #fff;
}
}
you could use a pseudo and a data attribute :
HTML5 is designed with extensibility in mind for data that should be associated with a particular element but need not have any defined meaning. data-* attributes allow us to store extra information on standard, semantic HTML elements without other hacks such as non-standard attributes, extra properties on DOM
overflow can be used and background-clip can help to mimic ribbon standing a bit outside
The background-clip CSS property specifies whether an element's background, either the color or image, extends underneath its border.
vmin or vmax units could be used to set font-size to resize the ribbon via em on padding and coordonates.
The viewport-percentage lengths
are relative to the size of the initial containing block. When the height or width of the initial containing block is changed, they are scaled accordingly.
eventually, shadow can be added and linear-gradient can help to draw slanted shadow's parts.
Demo:
body {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
grid-auto-rows: 1fr;
grid-gap: 2px;
height: 100vh;
padding: 5px;
margin: 0;
box-sizing: border-box;
}
grid-item {
background-color: lightgreen;
background-clip: content-box;
display: flex;
justify-content: center;
align-items: center;
position: relative;
overflow: hidden;
padding: 3px;
}
grid-item[data-class="new"]:before {
content: attr(data-class);
position: absolute;
font-size: 2vmax; /* update font-size */
top: 0.4em;
left: -1.3em;
padding: 0em 1.5em;
transform: rotate(315deg);
background-color:gold;
/* eventually add some shadow effects */
background-image:
linear-gradient(135deg, black 0.9em, transparent 1.15em),
linear-gradient(-135deg, black 0.9em, transparent 1.15em);
box-shadow: 0 0 3px;
}
<grid-item>see</grid-item>
<grid-item>full</grid-item>
<grid-item>page</grid-item>
<grid-item>then</grid-item>
<grid-item data-class="new">RESIZE</grid-item>
<grid-item>window</grid-item>
<grid-item>to</grid-item>
<grid-item>see</grid-item>
<grid-item>ribbon</grid-item>
<grid-item data-class="new">font&size</grid-item>
<grid-item>updates</grid-item>
<grid-item>F</grid-item>
<grid-item data-class="new">PRO</grid-item>
<grid-item>B</grid-item>
<grid-item>C</grid-item>
<grid-item>D</grid-item>
<grid-item>E</grid-item>
<grid-item>F</grid-item>
<grid-item>A</grid-item>
<grid-item>B</grid-item>
you need to put position: relative; on grid-item and then you can use absolute position on .ribbon-wrapper.
grid-item {
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
position: relative;
}
.ribbon-wrapper {
width: 85px; // the length should be not in px I think!
height: 88px; // the length should be not in px I think!
overflow: hidden;
position: absolute;
top: -3px;
left: -3px;
.ribbon {
font: bold 15px sans-serif;
color: #333;
text-align: center;
-webkit-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
position: relative;
padding: 7px 0;
top: 15px;
left: -30px;
width: 120px;
background-color: #ebb134;
color: #fff;
}
}
https://jsfiddle.net/thesouthstar86/rozkvsdh/6/
You can do it and also works for resize but it's a bit messy.
The spacer divs are there so you have the height. You need one on each side because you want PRO to be centered. We sacrifice 1px on each side to make this work and now ribbon-wrapper can be absolute
https://jsfiddle.net/rozkvsdh/9/
HTML
<grid-item>
<div class="ribbon-wrapper"><div class="ribbon">NEW</div></div>
<div class="spacer"></div>
<div>PRO</div>
<div class="spacer"></div>
</grid-item>
CSS
// this is new
.spacer {
height: 88px;
width: 1px;
}
grid-item {
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
position: relative; // added
}
.ribbon-wrapper {
width: 85px; // the length should be not in px I think!
height: 88px; // the length should be not in px I think!
overflow: hidden;
position: absolute;
top: 0; // edited
left: 0; // edited
}
The ribbon won't align left because it's an in-flow child of a flex container with justify-content: center. So both the ribbon and the content are centered side-by-side.
You can override that setting with margin-right: auto, which will left-align the ribbon, but it will also right-align the content.
You can insert an invisible spacer item to create equal balance in the container, keeping the content centered. But that's a bit involved and may be unnecessary.
Stick with CSS positioning properties. This will position the ribbon. Re-sizing it is another matter:
grid-item {
background-color: lightgreen;
display: flex;
justify-content: center;
align-items: center;
position: relative; /* establish nearest positioned ancestor for abspos containment */
}
.ribbon-wrapper {
overflow: hidden;
position: absolute;
top: 0;
left: 0;
bottom: 0;
}
.ribbon-wrapper .ribbon {
font: bold 15px sans-serif;
color: #333;
text-align: center;
transform: rotate(-45deg);
position: relative;
padding: 7px 0;
top: 15px;
left: -30px;
width: 15vw;
background-color: #ebb134;
color: #fff;
}
revised fiddle
Related
I have the following css for tickmark.
.Icon{
display: inline block;
height: 58px;
width: 29px;
border-bottom: 10px solid blue;
border-right: 10px solid blue;
transform: rotate(45deg);
border-radius: 8px;
}
I am trying to get tickmark with background circle. And learn in the process.
There are several approaches to achieving this effect (including CSS and SVG) but one of the most straightforward and portable is to combine a dash of CSS with the unicode character U+2713:
✓
In CSS, you can include extended unicode characters inside ::before and ::after pseudo-elements, using the format:
content: '\2713'
Working Example:
.tick-within-circle {
position: relative;
width: 48px;
height: 48px;
line-height: 50px;
text-align: center;
font-size: 44px;
font-weight: 900;
border: 8px solid rgb(0, 0, 255);
border-radius: 50%;
}
.tick-within-circle::before {
content: '\2713';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<div class="tick-within-circle"></div>
You can use Inline SVG in CSS. By doing so you can customize it's color, size and position. But for that to work SVG content be url-escaped.
Here's URL-escaped characters I used in snippet below
< => %3C
> => %3E
/ => %2F
# => %23
.tickmark-circle {
position: relative;
width: 35px;
height: 35px;
background-color: #db4437;
border-radius: 50%;
}
.tickmark-circle::before {
content: '';
position: absolute;
top: 0;
left: 0;
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' stroke='%23fff' stroke-width='5' fill='none' stroke-linecap='round' stroke-linejoin='round' class='css-i6dzq1' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5'/%3E%3C/svg%3E");
background-size: 20px;
background-position: center;
background-repeat: no-repeat;
width: 100%;
height: 100%;
}
<div class="tickmark-circle"></div>
Here are some ideas using just CSS.
This snippet takes your tick drawn using CSS and puts it into an after pseudo element on the element which has the Icon class. It introduces a before pseudo element which has the circular background color.
The pseudo elements are positioned at the end of a div.
This is all just for illustration, it depends on exactly how you want to use it whether you'd have the tick part in an actual element or attached as a pseudo element as here.
A CSS variable is used to describe the width of the left part of the tick itself and CSS calculations used after that to size the background etc. Again it all depends on what you want the final result to both look like and be used for as to whether you alter these settings or not.
.Icon {
display: inline-block;
position: relative;
overflow: visible;
--w: 29px;
font-size: calc(2 * var(--w));
}
.Icon::after {
content: '';
height: calc(2 * var(--w));
width: var(--w);
border-bottom: 10px solid blue;
border-right: 10px solid blue;
transform: rotate(45deg);
border-radius: 8px;
position: absolute;
padding: 10px;
box-sizing: border-box;
left: calc(100% + var(--w));
}
.Icon::before {
content: '';
height: calc(var(--w) * 3);
aspect-ratio: 1 / 1;
background-color: cyan;
background-repeat: no-repeat;
background-size: 200% auto;
position: absolute;
border-radius: 50%;
top: 50%;
left: 100%;
transform: translate(0, -50%);
z-index: -1;
}
<div class="Icon">Correct </div>
I know the height of the tree buttons (3rem, 3.75rem, 4.25rem). I need to place the i icon element at the right, in the middle of an imaginary square positioned at the right end of the button itself (purple area).
I've used right: 0 along with translateX(-50%) but it seems working only for the middle button (by chance). Any help is much appreciated.
.btn > i {
position: absolute;
z-index: 1;
top: 50%;
right: 0;
transform: translate(-100%, -50%);
}
If you know the dimensions of the icon, then you can use calculate()
lets say the icon is 10x20px
.btn > i {
width: 20px;
height: 10px;
position: absolute;
z-index: 1;
top: calculate(50% - 5px);
right: calculate(50% - 10px);
}
.btn > i:after {
display: block;
width: 20px;
height: 10px;
}
If you would like to avoid the absolute positioning, you can use flexbox:
.btn {
display: flex;
justify-content: center;
align-items: center;
}
this will effectively center any single element inside of flexbox
Just with a couple simple calc()'s and a few CSS variables this is quite simple
.btn-sm {
--btnSize: 3.00rem;
}
.btn-md {
--btnSize: 3.75rem;
}
.btn-lg {
--btnSize: 4.25rem;
}
.btn {
border: 2px solid purple;
color: purple;
display: inline-block;
font-family: sans-serif;
margin-bottom: 1rem;
position: relative;
border-radius: var(--btnSize);
line-height: var(--btnSize);
height: var(--btnSize);
padding: 0 calc( var(--btnSize) + 2rem ) 0 2rem;
}
.btn::before,
.btn::after {
position: absolute;
}
.btn::before {
inset: 0 0 0 auto;
content: "";
background: purple;
border-radius: 100%;
width: var(--btnSize);
}
.btn::after {
inset: 0 calc( var(--btnSize) / 2 ) 0 auto;
color: white;
content: "→";
transform: translateX(50%);
}
<div class="btn btn-sm">Approfondisci</div><br>
<div class="btn btn-md">Approfondisci</div><br>
<div class="btn btn-lg">Approfondisci</div><br>
I'm learning about CSS animations and am trying to animate this stamp which uses relative and absolute positioning. I want the animation to:
Start at it's original size.
Grow 2-3xs that size and be at the center of the screen.
Pause for 2-3 seconds seconds.
Shrink back down to it's original size and spot.
The problem I'm running into is keeping the elements positioned on top of the stamp in the same place as the transitions occur. Looking to keep it pure CSS if possible (*side note I haven't added any web-kit/browser support yet because I'm just trying to make it work first).
Here is the code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
height: 90vh;
justify-content: flex-end;
align-items: flex-start;
background: grey;
}
.park-img {
width: 10rem;
height: 11.2rem;
display: inline-block;
margin-left: 2px;
padding: 10px;
background: white;
position: relative;
top: 2rem;
left: -2rem;
/*-webkit-filter: drop-shadow(0px 0px 10px rgba(0,0,0,0.5));
/*The stamp cutout will be created using crisp radial gradients*/
background: radial-gradient( transparent 0px, transparent 4px, white 4px, white);
/*reducing the gradient size*/
background-size: 20px 20px;
/*Offset to move the holes to the edge*/
background-position: -10px -10px;
/*Animation*/
animation: stampAnimation 9s ease-in-out;
}
#keyframes stampAnimation {
0% {}
50% {
transform: scale(3, 3) translate(-35%, 35%);
}
75% {
transform: scale(3, 3) translate(-35%, 35%);
}
}
.stampText {
position: relative;
top: -1rem;
left: -1.8rem;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
color: #fafafa;
text-transform: uppercase;
animation: stampAnimation 9s ease-in-out;
}
.park-name {
font-weight: bold;
text-align: center;
font-size: 1rem;
}
.park-title {
width: 90%;
overflow: hidden;
text-align: center;
font-size: .5rem;
}
.park-title:before,
.park-title:after {
background-color: #fafafa;
content: "";
display: inline-block;
height: 1px;
position: relative;
vertical-align: middle;
width: 10%;
}
.park-title:before {
right: 0.5rem;
margin-left: -50%;
}
.park-title:after {
left: 0.5rem;
margin-right: -50%;
}
<div class="park-stamp">
<img src="https://res.cloudinary.com/saveallthethings/image/upload/v1614633821/daniel-burka-X_IwSPO2GH0-unsplash_zvoyst.jpg" class="park-img" />
<div class="stampText">
<div class="park-name">Zion</div>
<div class="park-title">National Park</div>
</div>
</div>
As well as the codepen:
https://codepen.io/aspirationalhobbit/pen/GRNPqxw?editors=0100
I have edited your code to make changes that are different from my initial answer.
Check https://codepen.io/udabasili/pen/VwmqmQK?editors=1100.
Basically, I created a css for the container of your element and moved the animation there. I also removed the translate from your animation. Check the css in the codepen to see the changes
.park-stamp{
animation: stampAnimation 9s ease-in-out infinite;
}
i use CSSGrid with an hover effect who works great on desktop, but i have a bug on mobile and can't find the problem.
You can see the page here, and look on desktop on mobile view: http://lafabutineuse.flywheelsites.com/realisations
I defined my image title and link to be absolute and 100% height of the div.
The code of my title on image:
h2 a, h2 {
background: rgba(0,0,0,0);
color: rgba(0,0,0,0);
position: absolute;
left: 0;
right: 0;
bottom: 0;
align-items: center;
padding: 10px;
padding-bottom: 10px!important;
text-align: center;
height: 100%;
z-index: 10000;
transition-property: background;
-webkit-transition-property: background;
transition-duration: 0.5s;
-webkit-transition-duration: 0.5s;
}
and same code on hover but with differents colors:
h2 a:hover, h2:hover {
background: rgba(224,197,76,0.61);
color: white;
position: absolute;
left: 0;
right: 0;
bottom: 0;
align-items: center!important;
vertical-align: middle;
padding: 10px;
padding-bottom: 10px!important;
text-align: center!important;
justify-content: center;
display: flex;
height: 100%;
z-index: 10000;
}
I tried some codes to fix the problem but can't achieve to keep the same effect on mobile.
Do you have any idea please?
Thank you
You have not explicitly set position for .et_pb_grid_item on screens smaller then 980px - that's why your hover-link takes 100% of .et_pb_portfolio_items.
Set position: relative; for .et_pb_grid_item and that should fix the hover problem.
.et_pb_grid_item {
position: relative;
}
I have code like this:
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
position: relative;
white-space: pre;
display: inline;
top: -27px;
left: -29px;
width: 200px;
text-align: center;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
How can I center the text inside :before pseudo element to be in the middle of the span? Is it possible?
The best thing would be to position the before pseudo element absolutely with respect to the span using the popular centering technique:
top: 0;
left: 50%;
transform: translate(-50%, -25px);
Note that -25px is to offset the text above the circles (which has height 25px) - see demo below:
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
position:relative;
}
span:before {
content: attr(data-value);
position: absolute;
white-space: pre;
display: inline;
top: 0;
left: 50%;
transform: translate(-50%, -25px);
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
Source
From MDN:
[the :before pseudo-element] is inline by default
Giving inline elements a width does nothing, so you need to style it as display: block (or inline-block if that is more appropriate). It also turns out that you need to adjust the left value to approximately -88px to get the text centred over the circle.
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
position: relative;
white-space: pre;
display: inline;
top: -27px;
left: -88px;
width: 200px;
text-align: center;
display: block;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
I recommend against using negative translations. It might end up outside the viewport if you don't do it enough carefully.
Moreover, you shouldn't insert contents with pseudo-elements. Pseudo-elements should only be used for styling purposes. Like this:
body {
display: inline-block;
}
span {
display: block;
text-align: center;
}
span:after {
content: '';
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 10px auto 30px;
display: block;
}
<span>November 2016</span>
<span>May 2016</span>
The text inside the span is centered due to text-align: center.
The pseudo-element circle is centered due to margin-left: auto and margin-right: auto.
We should use LOGICAL CODE and not any hit and trail and playing around with numbers!
I used flex in the pseudo element to center it first upon the span element.
Then i used transform to Logically position the pseudo element.
/*styling to just make the presentation look good*/
body{
border:5px solid black;
padding:50px;
display:flex;
flex-direction: column;
justify-content:center;
align-items:center;
}
/* main stylings start here*/
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
width:150px;
border:solid black 1px;
/*use flex to center it to middle & upon the span*/
display:flex;
justify-content:center;
align-items:center;
/*use transform and position it LOGICALLY (by considering border widths of the parent span and ofcourse using calc() )*/
transform: translate(calc(-50% + 2 * 6px), calc(-100% - 6px));
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>
I would request to use LOGICAL Code rather than design-breaking hit and trail values.
Write Responsive Code. Happy Coding!
I was beaten to this, but here is my solution:
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
position: relative;
white-space: pre;
display: inline-block;
top: -27px;
left: -50px;
width: 125px;
text-align: center;
}
The changes are to use inline-block display on the :before style and to adjust the left and width of the text.
Add display:inline-block; and add margin-left:-87px. where 87px derived from
100px(50% of whole width 200px)-13px(50% of span width 25px)
span {
border-radius: 50%;
background-color: #d8d9dd;
border: 6px solid #262c40;
width: 25px;
height: 25px;
margin: 30px 0 0 40px;
display: block;
}
span:before {
content: attr(data-value);
position: relative;
white-space: pre;
display: inline-block;
top: -27px;/*
left: -29px;*/
margin-left: -87px;
width: 200px;
text-align: center;
}
<span data-value="November 2016"></span>
<span data-value="May 2016"></span>