I am trying to create a hexagon using CSS. There are a number of questions about this already, but in my specific case I need it composed of 3 identical shapes that are different colors.
There are 2 specific requirements:
The overall size of the hexagon must be controllable by a single value. In my case that is the width of the .hexagon-wrapper class
The hexagon shape must be centered horizontally and vertically within it's parent (.hexagon-wrapper), and that wrapper must also be centered horizontally and vertically within its parent (the outermost div)
You'll notice there are some problems with my attempt:
The 3 pieces that make up the hexagon arent tightly aligned,
and the overall shape starts to break apart when you change
.hexagon-wrapper width
I'm using some magic numbers to translate the individual pieces, and they don't guarantee that the pieces will stick together after resizing, nor do they really guarantee that the elements are perfectly centered horizontally and vertically
Is there an easier way to do this, or some simple math that I'm missing? Basically, how do I keep the pieces together, and how do I ensure everything is centered?
I did consider creating a 3D cube and using transform3d to ensure everything sticks together, but I do not want to go with this approach because I have had many anti-aliasing issues when using transform3d and want to avoid that altogether
.hexagon-wrapper {
display: flex;
position: relative;
background-color: green;
width: 40%;
height: 100%;
margin: auto;
}
.hexagon-part-red {
position: relative;
width: 27.85714285714286%;
padding: 0 0 32.16760145166612% 0;
transform: translate(112%, -50%) rotate(-60deg) skewY(30deg);
background: red;
margin: auto;
}
.hexagon-part-yellow {
position: relative;
width: 27.85714285714286%;
padding: 0 0 32.16760145166612% 0;
transform: translate(-49%, 25%) rotate(0deg) skewY(30deg);
background: yellow;
margin: auto;
}
.hexagon-part-blue {
position: relative;
width: 27.85714285714286%;
padding: 0 0 32.16760145166612% 0;
transform: translate(-69%, 25.1%) rotate(60deg) skewY(30deg);
background: blue;
margin: auto;
}
<div>
<span class="hexagon-wrapper">
<div class="hexagon-part-red"></div>
<div class="hexagon-part-yellow"></div>
<div class="hexagon-part-blue"></div>
</span>
</div>
Here is an easier idea where you don't need any complex calculation and a lot of transform:
.hexagon-wrapper {
position: relative;
background-color: green;
width: 40%;
margin: auto;
display: flex;
justify-content: center;
}
.hexagon-part-red,
.hexagon-part-yellow,
.hexagon-part-blue {
width: 30%;
display: inline-flex;
}
.hexagon-part-red:before,
.hexagon-part-yellow:before,
.hexagon-part-blue:before {
content: "";
padding-top: 115.47%; /* 100/cos(30deg) */
}
.hexagon-part-red {
position: absolute;
top: -50%;
height: 100%;
width: 60%;
background: red;
clip-path: polygon(0 50%, 50% 0, 100% 50%, 50% 100%);
}
.hexagon-part-yellow {
transform: skewY(30deg);
transform-origin: left;
background: yellow;
}
.hexagon-part-blue {
transform: skewY(-30deg);
transform-origin: right;
background: blue;
}
body {
margin: 0;
display: flex;
height: 100vh;
}
<div class="hexagon-wrapper">
<div class="hexagon-part-red"></div>
<div class="hexagon-part-yellow"></div>
<div class="hexagon-part-blue"></div>
</div>
Related
This question already has answers here:
Shape with a slanted side (responsive)
(3 answers)
Closed 5 years ago.
I have been searching for a few days now for code to make the right edge of a div slant 45 degrees. Here is an image example of what I am particularly attempting to get...
There seems to be a lot of examples of 'slanted-edge' divs, but I can't find any with the particular right-side slanted.
I have spend a great deal of time trying to alter the codes of the others, but it ends up in a mess.
This is the original CSS code I was experimenting with to get the results I need...
div {
position: relative;
display: inline-block;
padding: 1em 5em 1em 1em;
overflow: hidden;
color: #fff;
}
div:after {
content: '';
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
background: #000;
-webkit-transform-origin: 100% 0;
-ms-transform-origin: 100% 0;
transform-origin: 100% 0;
-webkit-transform: skew(-45deg);
-ms-transform: skew(-45deg);
transform: skew(-45deg);
z-index: -1;
}
body {
background:
url('https://farm3.staticflickr.com/2878/10944255073_973d2cd25c.jpg');
background-size: cover;
}
Here is the HTML....
<div>Slanted div text</div>
<div>
Slanted div text<br/>
on several lines<br/>
Another line
</div>
<div>Wider slanted div text with more text inside</div>
Create your div, then overlay an absolutely-positioned, rotated pseudo-element to create the slanted impression.
div {
height: 50px;
width: 300px;
background-color: black;
position: relative;
overflow: hidden;
}
div:after {
height: 100%;
width: 100%;
background-color: white;
position: absolute;
content: "";
transform: rotate(45deg);
transform-origin: bottom right;
}
<div></div>
I have two identical elements. The top one, I'm scaling to double the size and then centering over the normal-sized one. I want its inner element to then be scaled back down to normal size and placed exactly where the normal sized element's inner element is placed.
This seems to be impossible. There seems to be no logic in the scaling + translation of position.
How would I do this?
https://jsfiddle.net/0urdrvao/
HTML:
<div class="top">
<div class="inner">
Inner
</div>
</div>
<div class="bottom">
<div class="inner">
Inner
</div>
</div>
CSS:
body, html
{
margin: 0px;
padding: 0px;
width: 100%;
height: 100%;
}
.top,
.bottom
{
position: relative;
top: 0px;
left: 0px;
width: 300px;
height: 300px;
background-color: gray;
z-index: 0;
}
.top
{
position: fixed;
transform-origin: 0 0 0;
transform: translate(-150px, -150px) scale(2);
opacity: .5;
z-index: 1;
}
.inner
{
position: relative;
top: 20vh;
left: 0px;
width: 100px;
height: 40px;
background-color: red;
}
.top .inner
{
/* This doesn't work */
transform: translate(150px,150px) scale(.5);
/* This also doesn't work (doing half)*/
/*transform: translate(75px,75px) scale(.5);*/
/* This also doesn't work (doing double)*/
/*transform: translate(300px,300px) scale(.5);*/
transoform-origin: 0 0 0;
background-color: yellow;
}
Since the top: 20vh will be scaled times 2, the transform-origin should be 0 -20vh.
When reverse a scale/translate you need to go backwards and start with scale and then the translate
.top{
position: fixed;
transform-origin: 0 0;
transform: translate(-150px, -150px) scale(2);
opacity: .5;
z-index: 1;
}
.top .inner{
transform: scale(.5) translate(150px, 150px);
transform-origin: 0 -20vh;
background-color: yellow;
}
Updated fiddle
Or one could do like this, setting origin to 0 0 and transform: scale(.5) translate(150px,150px) translateY(-20vh);
Updated fiddle
I would like to show the image with a non glassy display. Similar to the following one,
I am using the image as it is. I would like to show that with matte finish.
normal image:
Matte finish:
I am not able find it online. May be I am not using the right search keywords. Could anyone help me with this?
Inside a container I did put an image with reduced contrast / brightness / saturation plus a little bit of blur (all these four effects made by CSS filter). The image could've be placed as the container background but I wanted to apply these filters so it went separated.
After it, there's a colored layer with transparency covering the whole area. The letter represents the page's content that can be anything.
UPDATE: multiple filters must be all in a row, like it is on this latest update:
body {
width: 100%;
height: 100vh;
margin: 0px;
font-family: Georgia, serif;
}
#container {
width: 100%;
height: 100%;
position: relative;
background-color: navy;
overflow: hidden;
}
#thepic {
width: 100vw;
height: 100vh;
object-fit: cover;
-webkit-filter: brightness(90%) contrast(90%) blur(2px) grayscale(10%);
filter: brightness(90%) contrast(90%) blur(2px) grayscale(10%);
}
#color_layer {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: navy;
opacity: 0.3;
}
#content {
position: absolute;
top: 50%;
-webkit-transform: translateY(-50%);
-ms-transform: translateY(-50%);
transform: translateY(-50%);
left: 0;
right: 0;
margin: auto;
text-align: center;
}
h1 {
display: inline-block;
color: white;
text-shadow: 1px 2px 2px #000;
font-size: 4em;
font-weight: 100;
letter-spacing: 2px;
text-align: center;
vertical-align: middle;
}
#letter {
vertical-align: middle;
}
<div id=container>
<img id=thepic src="http://i.imgur.com/s9J4MnI.jpg">
<div id=color_layer></div>
<span id=content><img id=letter src="http://i.imgur.com/CB1vUqy.png" alt=img><h1> 書面</h1></span>
</div>
#freestock.tk - That's the idea I had in mind also.
Here's another way to do it with less markup:
img {
max-width: 100%;
height: auto;
}
.container {
position: relative;
z-index: -1;
}
.container:before {
content: "";
position: absolute;
z-index: 1;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.5);
}
<div>
<h1>Original Image</h1>
<img src="http://i.imgur.com/WjbwTUH.jpg">
</div>
<div class="container" id="content">
<h1> With Transparent Overlay </h1>
<img src="http://i.imgur.com/WjbwTUH.jpg">
</div>
In this example, I put the image inside a container that is relatively positioned. The z-index is -1 so it will be behind the next layer.
Then I used a pseudo element that is absolutely positioned so it will stretch across the whole width of the container and cover the image. The positive z-index sets it on top of the first layer. Rather than setting an opacity, I used an rgba value for the background color. The first three numbers or the red, green, and blue values as usual, but the last number is a decimal between 0 and 1 that sets the opacity level. I made it a little darker than you probably want just so you can see the difference. You may also choose a different color to fit your image.
For reference: http://nicolasgallagher.com/css-background-image-hacks/
I'm scaling a div up with the transform property, but I want to keep its children (which have 1px width or height) the same size. I counter-scaled them by .5, with the expected result that an element of 1px scaled by 2, and then .5, should end up back at 1px, but they wind up a blurry 2px.
Here's the box before scaling it:
.container {
width: 200px;
height: 200px;
margin: 100px;
background-color: #EEE;
position: absolute;
}
.outline {
position: absolute;
background: #1899ef;
z-index: 999999;
opacity: 1 !important;
}
.outlineBottom, .outlineTop {
width: 100%;
height: 1px;
}
.outlineLeft, .outlineRight {
height: 100%;
width: 1px;
}
.outlineRight {
right: 0px;
}
.outlineBottom {
bottom: 0px;
}
<div class="container">
<div class="outline outlineTop"></div>
<div class="outline outlineRight"></div>
<div class="outline outlineBottom"></div>
<div class="outline outlineLeft"></div>
</div>
As you can see, the elements at the edges are a clear, dark 1px blue. Here's what the box looks like after scaling, though:
.container {
width: 200px;
height: 200px;
margin: 100px;
background-color: #EEE;
position: absolute;
transform: scale(2);
}
.outline {
position: absolute;
background: #1899ef;
z-index: 999999;
opacity: 1 !important;
transform: scale(.5);
}
.outlineBottom, .outlineTop {
width: 100%;
height: 1px;
transform: scale(1,.5);
}
.outlineLeft, .outlineRight {
height: 100%;
width: 1px;
transform: scale(.5,1);
}
.outlineRight {
right: 0px;
}
.outlineBottom {
bottom: 0px;
}
<div class="container">
<div class="outline outlineTop"></div>
<div class="outline outlineRight"></div>
<div class="outline outlineBottom"></div>
<div class="outline outlineLeft"></div>
</div>
And here's a post-scaled render from Chrome 41.0.2272.89 Mac, which is what I'm running.
Adding transform-3d(0, 0, 0) didn't appear to help. A solution was found using the zoom property, but since zoom isn't well supported I'd like to avoid that. Adding filter: blur(0px); didn't appear to have any effect either.
It was posited in chat that perhaps the children are first scaled to .5 and then doubled in size, causing them to be scaled down to .5px and then back up from there. Is there any way to ensure the order that they're rendered in causes them to first be scaled up to 2px and then halved? Against my better judgement, I tried forcing the render order with JS, but unsurprisingly, that didn't have any effect (though, interestingly, the bottom element did maintain its original color).
Failing that, are there any other solutions floating around out there? I can't be the only one who's run into this problem.
It is to do with the default transform-origin on the scaled elements. It defaults to 50% 50% for any element being transformed, but this has issues when scaling down 1px values as it has to centre the scale on a half pixel and the rendering of the elements has issues from here on out. You can see it working here with the transform-origin moved to the relevant extremes for each item.
A bit of playing about shows that this same blurring happens on scaled elements for any dimension where the scaling ends up halving a pixel.
body {
padding: 1em;
}
.container {
width: 200px;
height: 200px;
margin: 100px;
background-color: #EEE;
position: absolute;
transform: scale(2);
}
.outline {
position: absolute;
background: #1899ef;
z-index: 999999;
opacity: 1 !important;
}
.outlineBottom, .outlineTop {
width: 100%;
height: 1px;
transform: scale(1, 0.5);
}
.outlineBottom {
bottom: 0;
transform-origin: 0 100%;
}
.outlineTop {
transform-origin: 0 0;
}
.outlineLeft, .outlineRight {
height: 100%;
width: 1px;
transform: scale(.5,1);
}
.outlineRight {
right: 0px;
transform-origin: 100% 0;
}
.outlineLeft {
left: 0px;
transform-origin: 0 0;
}
<div class="container">
<div class="outline outlineTop"></div>
<div class="outline outlineRight"></div>
<div class="outline outlineBottom"></div>
<div class="outline outlineLeft"></div>
</div>
I want to make a css box with rotation. here is the image that I'd like:
Can anyone help me to make the same? Here is the code that I have used.
.yr_highlights
{
background: none repeat scroll 0 0 #000000;
height: 30px;
margin: 24px auto 0;
text-align: center;
transform: skewY(-7.4deg);
width: 20%;
}
<div class="yr_highlights"></div>
See this Fiddle
.box {
background: red;
width: 200px;
height: 50px;
-webkit-transform: skewY(-7deg) skewX(-17deg);
-moz-transform: skewY(-7deg) skewX(-17deg);
transform: skewY(-7deg) skewX(-17deg);
margin: 50px 0 0 50px;
}
.yr_highlights {
transform: rotate(-10deg);
}