How to crop an element and keep the size adjusted - html

I have an element which I would like to crop x% of it from the right, and so the width will automatically decrease by half to fit the new content.
Currently I'm using this:
div{
display:flex;
justify-content: space-evenly;
width:180px;
}
i{
color: yellow;
}
span i{
position:relative;
left: 50%;
}
span{
overflow: hidden;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<span>
<i class="fas fa-2x fa-star"></i>
</span>
</div>
But as you can see when using it the span keeps it's original width and doesn't crop
Or using clip-path
so it creates an extra gap between the half star and the solid star before/after it.
I have tried using transform: translateX(-x%); on the container but it sabotages the entire layout and every element positioned after it gets a x% offset.
Is there a way to crop the element and so it's size?
NOTE: the real element size is dynamic. I prefer a pure css solution that doesn't evolve using constants /JS
Thanks

edit, after understanding the question, you may use width + overflow
If it is dynamic and can show up many times, you may use var() to update the value on the fly
examples
Why do i use em for sizing ? - because its size is about its own font-size : here : fa-2x in your question , which em will match even if the class turns to be fa-4x .
div{
display:flex;
justify-content: space-evenly;
width:180px;
margin:1em;
filter:drop-shadow(0 0 3px)
}
i{
color: yellow;
}
div i:last-of-type{
width: var(--size);
overflow:hidden;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div style="--size: calc(1em * 0.3)">
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>30%
</div>
<div style="--size: calc(1em * 0.6)">
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>60%
</div>
<div style="--size: calc(1em * 0.7)">
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>70%
</div>
You may use clip-path, it will allow you to cut off a portion of the element . % can be used .
It also can allow you to cut it off with different shapes .
This will help you create your first clip-path https://bennettfeely.com/clippy/
specification https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path
examples
div{
display:flex;
justify-content: space-evenly;
width:180px;
margin:1em;
filter:drop-shadow(0 0 3px)
}
i{
color: yellow;
}
div i:last-of-type{
clip-path: polygon(0 0, 60% 0, 60% 100%, 0% 100%);
}
/*cut half of its surface , but differently*/
[title] i:last-of-type{
clip-path: polygon(0 40%, 100% 40%, 100% 100%, 0% 100%);
}
[class] i:last-of-type{
clip-path: polygon(0 0, 100% 0, 0 100%, 0% 100%);
}
[id] i:last-of-type{
clip-path: polygon(0 0, 100% 0, 0 100%, 100% 100%);
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>60%
</div>
<div title="2.6">
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>60%
</div>
<div class>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>50%
</div>
<div id >
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>50%
</div>

You should specify the width of each star, which is 36px in this case. Then you can just set the width to 16px for the last star and add overflow hidden.
div{
display:flex;
justify-content: space-evenly;
width:180px;
}
i{
color: yellow;
width: 36px;
}
.half-star {
overflow: hidden;
width: 16px;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star half-star"></i>
</div>

You can use the clip property and just for example do that
clip: rect(0px,60px,200px,0px); it should split it in half

Use fa-star-half as an alternative to custom styles. This will ensure dynamicity.
div {
display: flex;
justify-content: space-evenly;
width: 180px;
}
i {
color: yellow;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star-half"></i>
</div>
Solution w/o fa-star-half.
I called your custom span with the customs styles .custom. This solution requires removing justify-content: space-evenly and uses a calculated width on your span's that are not custom.
However, you still want the .custom span to be factored into this width. So you can set something like span:not(.custom) { width: calc(100% / 3); } Then, you will want to set text-align: center; to the non custom spans's also.
div {
display: flex;
width: 180px;
}
i {
color: yellow;
}
span.custom i {
position: relative;
left: 50%;
}
span.custom {
overflow: hidden;
}
span:not(.custom) {
width: calc(100% / 3);
text-align: center;
}
span {
outline: black 1px dotted;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div>
<span>
<i class="fas fa-2x fa-star"></i>
</span>
<span>
<i class="fas fa-2x fa-star"></i>
</span>
<span class="custom">
<i class="fas fa-2x fa-star"></i>
</span>
</div>

If you're looking to make the star half, you could use <i class="fa fa-star-half-o" aria-hidden="true"></i> instead of trying to crop it in half and then fit to the content.
Please let me know if I have misunderstood your question.
EDIT:
I would make a parent container for each star that is responsible for the width and height, and let the child base its width on the preferred percentage.
.star-row {
display: flex;
gap: 5px;
}
i {
color: yellow;
overflow: hidden;
}
.last-star {
width: 50%;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div class="star-row">
<div class="star-container">
<i class="fas fa-2x fa-star"></i>
</div>
<div class="star-container">
<i class="fas fa-2x fa-star last-star"></i>
</div>
</div>

I cropped the stars using a span outside (and I replaced the div with span).
span{
display:flex;
justify-content: space-evenly;
overflow: hidden;
width: 95px;
}
i{
color: gold;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<span>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star" style="width:calc(36px / 2);"></i>
</span>

it's simple you just need to use negative for margin element.
margin-right:-18px;
div{
display:flex;
justify-content: space-evenly;
width:180px;
}
i{
color: yellow;
}
span i{
margin-right:-18px;
}
span{
background:red;
overflow: hidden;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<span>
<i class="fas fa-2x fa-star"></i>
</span>
</div>

Using clip-path can be a practical solution for this case.
It's not size dependent, and you can use any value between 0-100% for the --percentage variable.
div{
display:flex;
justify-content: space-evenly;
width:180px;
}
i{
color: yellow;
}
i:last-child{
--percentage: 50%;
clip-path: polygon(0 0, var(--percentage) 0, var(--percentage) 100%, 0 100%);
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
</span>
</div>
If the last star bounding box is a concern, you should be able to achieve that by providing a width like this.
div{
display:flex;
justify-content: space-evenly;
width: 180px;
--star-count: 5;
--star-width: calc(100% / var(--star-count));
--last-star-crop: 1/2;
}
i{
width: var(--star-width);
color: yellow;
}
i:last-child{
width: calc(var(--star-width) * var(--last-star-crop));
overflow: hidden;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.min.css">
<div>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
<i class="fas fa-2x fa-star"></i>
</span>
</div>
Note: FontAwesome uses font-size to dictate icon sizing, due to that smaller container widths can cause distortion.

Related

How to get text displayed below font awesome icon?

I have this html below where I am using font awesome icons. What I would like is the for text for each icon (in the example below joinery and plumbing to appear below it's relevant font awesome icon). At the moment the text is display to the right of the icon half way up.
<div class="icons">
<span class="fa-stack fa-4x">
<i class="far fa-circle fa-stack-2x icon-background"></i>
<i class="fa fa-hammer fa-stack-1x"></i>
</span>
<span class="icons-text">Joinery</span>
<span class="fa-stack fa-4x">
<i class="far fa-circle fa-stack-2x icon-background"></i>
<i class="fa fa-wrench fa-stack-1x"></i>
</span>
<span class="icons-text">Plumbing</span>
</div>
.icon-background {
color: #000000;
}
.icons{
text-align:center;
}
.icons-text{
color:#000000;
font-size:10px;
padding:5px 0 10px 0;
text-transform:uppercase;
letter-spacing:1px;
}
I tried including display:block within icon.text and this does add the text below the icon, but what is also does it stack the icons vertically and not keeping them next to each other horizontally.
There are several ways of doing this, depending on exactly what is required. One is to make the spans into divs, then the browser automatically stacks the text below the icon, but to make this icon/text stay on the same line as the next one, wrap each set in a div - I've given it the class 'trade' - and float that.
.icon-background {
color: #000000;
}
.icons{
text-align:center;
}
.icons-text{
color:#000000;
font-size:10px;
padding:5px 0 10px 0;
text-transform:uppercase;
letter-spacing:1px;
}
div.trade {
float:left;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" crossorigin="anonymous" />
<div class="icons">
<div class="trade">
<div class="fa-stack fa-4x">
<i class="far fa-circle fa-stack-2x icon-background"></i>
<i class="fa fa-hammer fa-stack-1x"></i>
</div>
<div class="icons-text">Joinery</div>
</div>
<div class="trade">
<div class="fa-stack fa-4x">
<i class="far fa-circle fa-stack-2x icon-background"></i>
<i class="fa fa-wrench fa-stack-1x"></i>
</div>
<div class="icons-text">Plumbing</div>
<div>
</div>
There is a cleaner way to do it, if you'd like:
.icons .fa {
display: inline-block;
padding: 0 0 10px;
color: #000;
font-size: 10px;
text-align: center;
text-transform: uppercase;
letter-spacing: 1px;
}
.icons .fa:before {
display: block;
width: 1.5em; height: 1.5em;
margin: 0 auto 5px;
border: solid .2em; border-radius: 55%;
font-size: 6.4em;
line-height: 1.5em;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.8.2/css/all.min.css" rel="stylesheet" />
<div class="icons">
<span class="fa fa-hammer">Joinery</span>
<span class="fa fa-wrench">Plumbing</span>
</div>

How to color parts of character in HTML?

On my website, I'm using a user rating with five stars. So each user can choose from one to five stars.
And I would like to show the average user rating, with partial colored stars. For example: The average rating is 3.5 stars, three stars should be colored completely, and the fourth star should be colored with 50% horizontal.
I'm using the Font Awesome for showing the stars. So each star is a character, not an image.
Is there a solution for this, without using an image? Maybe with CSS?
Until now, I know only solutions to color complete characters with style="color: yellow;", but I would like to color 50% of the fourth character...
You could achieve this by having 2 instances of 5 stars, 1 set is yellow stars and 1 is gray. Position the yellow one on top then set the width to a percentage and hide the overflow
.rating {
display: inline-block;
position: relative;
line-height: 1em;
}
.rating__overlay {
color: yellow;
position: absolute;
top: 0;
left: 0;
width: 70%;
white-space: nowrap;
overflow: hidden;
}
.rating__base {
color: #ccc;
white-space: nowrap;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="rating">
<div class="rating__overlay">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
</div>
<div class="rating__base">
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
<i class="fas fa-star"></i>
</div>
</div>

How to display some elements into a div modifying the width [duplicate]

This question already has answers here:
CSS for star ratings via FontAwesome
(7 answers)
Closed 4 years ago.
I want to display the div with the filled stars on the div with the empty stars. The result that I want is to reveal the filled stars modifying the width of the div.
I try to explain better. If with a width of 100px 5 filled stars are displayed, I want to be able to set the width to 83px and display only 4,5 stars.
My problem is that now if I set a div of 83px, the last star floats under the other stars. I would like to keep the stars in a fixed position and show also portions of it.
This is my code:
.rating-star {
font-size: 20px;
color: green;
}
.vote-container {
position: relative;
}
.full-stars {
position: absolute;
}
.vote,
.vote-number {
color: green;
}
.full-stars {
display: block;
height: 18px;
overflow: hidden;
width: 83px;
}
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="vote-container" id="vote-container_1">
<span class="full-stars">
<i class="fa rating-star fa-star"></i>
<i class="fa rating-star fa-star"></i>
<i class="fa rating-star fa-star"></i>
<i class="fa rating-star fa-star"></i>
<i class="fa rating-star fa-star"></i>
</span>
<i class="fa rating-star fa-star-o"></i>
<i class="fa rating-star fa-star-o"></i>
<i class="fa rating-star fa-star-o"></i>
<i class="fa rating-star fa-star-o"></i>
<i class="fa rating-star fa-star-o"></i>
</div>
You will have to add just this code in .full-stars class.
white-space:nowrap

div has margin, but not in the inspector [duplicate]

This question already has answers here:
How to place two divs next to each other? [duplicate]
(13 answers)
Closed 5 years ago.
I have a <div> with two <div>s in it, but the first <div> called facePlus has a margin when you hover over it in the inspector, and when you scroll down to the table it says it doesn't have it:
.facePlus {
width: 50%;
margin-right: 0%;
}
.twittIn {
width: 50%;
position: absolute;
left: 50%;
}
.socialMedia {
display: inline;
}
<div class="socialMedia">
<div class="facePlus">
<i class="fa fa-facebook" aria-hidden="true"></i> Facebook<br>
<i class="fa fa-google-plus" aria-hidden="true"></i> Google plus
</div>
<div class="twittIn">
<i class="fa fa-twitter" aria-hidden="true"></i>Twitter<br>
<i class="fa fa-linkedin" aria-hidden="true"></i>Linkedin
</div>
</div>
how can I put them next to each other?
use flexbox
.socialMedia {
display: flex;
}
.socialMedia>div {
flex: 1
}
<div class="socialMedia">
<div class="facePlus">
<i class="fa fa-facebook" aria-hidden="true"></i> Facebook<br>
<i class="fa fa-google-plus" aria-hidden="true"></i> Google plus
</div>
<div class="twittIn">
<i class="fa fa-twitter" aria-hidden="true"></i>Twitter<br>
<i class="fa fa-linkedin" aria-hidden="true"></i>Linkedin
</div>
</div>
Two approaches for you...
You can use the display property to place your divs side by side...
.facePlus {
width: 48%;
display: inline-block;
}
.twittIn {
width: 48%;
display: inline-block;
}
<div class="socialMedia">
<div class="facePlus">
<i class="fa fa-facebook" aria-hidden="true"></i> Facebook<br>
<i class="fa fa-google-plus" aria-hidden="true"></i> Google plus
</div>
<div class="twittIn">
<i class="fa fa-twitter" aria-hidden="true"></i>Twitter<br>
<i class="fa fa-linkedin" aria-hidden="true"></i>Linkedin
</div>
</div>
Or you can use flexbox which you can read more about here:
.socialMedia {
display: flex;
}
.facePlus,
.twittIn {
flex: 1;
}
<div class="socialMedia">
<div class="facePlus">
<i class="fa fa-facebook" aria-hidden="true"></i> Facebook<br>
<i class="fa fa-google-plus" aria-hidden="true"></i> Google plus
</div>
<div class="twittIn">
<i class="fa fa-twitter" aria-hidden="true"></i>Twitter<br>
<i class="fa fa-linkedin" aria-hidden="true"></i>Linkedin
</div>
</div>

Vertical Align Text After Font Icon

<div class="col-md-4">
<span class="fa-stack fa-2x">
<i class="fa fa-circle fa-stack-2x blue"></i>
<i class="fa fa-wifi fa-stack-1x white"></i>
</span>
<h4 class="blue">Free wifi</h4>
</div>
How can I display h4 element on the right of the icon and vertically aligned? Should I float left the span?
One of the ways would be to use inline-block display and middle align it - see demo below:
.wrapper > * {
display: inline-block;
vertical-align: middle;
}
.blue {
color: blue;
}
.white {
color: white;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<div class="col-md-4 wrapper">
<span class="fa-stack fa-2x">
<i class="fa fa-circle fa-stack-2x blue"></i>
<i class="fa fa-wifi fa-stack-1x white"></i>
</span>
<h4 class="blue">Free wifi</h4>
</div>
Use CSS Flexbox. Make a parent <div> that wraps icon and text into it (in my case its icon-holder) and make it a flexbox container using display: flex.
Have a look at the snippet below:
.icon-holder {
display: flex; /* Flex Container */
align-items: center; /* Vertically Align Content */
}
.blue {
color: #33b5e5;
}
span {
color: #fff;
}
h4 {
padding-left: 5px;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="col-md-4">
<div class="icon-holder">
<span class="fa-stack fa-2x">
<i class="fa fa-circle fa-stack-2x blue"></i>
<i class="fa fa-wifi fa-stack-1x white"></i>
</span>
<h4 class="blue">Free wifi</h4>
</div>
</div>
Hope this helps!
You can use display: flex and can do something like below :
.col-md-4 {
display: flex;
align-items: center;
}
.blue {
color: blue
}
.white {
color: white;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<div class="col-md-4 wrapper">
<span class="fa-stack fa-2x">
<i class="fa fa-circle fa-stack-2x blue"></i>
<i class="fa fa-wifi fa-stack-1x white"></i>
</span>
<h4 class="blue">Free wifi</h4>
</div>