Full width overlapping triangles - html

I currently need to make something with CSS that would look like this:
I managed to do it with this:
.top {
position: relative;
}
.top .gray-bar {
position: absolute;
width: 100%;
height: 50px;
background-color: #cdcbcc;
-ms-transform: rotate(1.2deg);
transform: rotate(1.2deg);
margin-top: -25px;
z-index: 2;
}
.top .cyan-bar {
position: absolute;
width: 100%;
height: 90px;
background-color: #2ca1ab;
-ms-transform: rotate(-3deg);
transform: rotate(-3deg);
z-index: 1;
margin-top: -30px;
margin-left: -400px;
}
.top .purple-bar {
position: absolute;
width: 100%;
height: 50px;
background-color: #b71e4c;
-ms-transform: rotate(0.7deg);
transform: rotate(0.7deg);
margin-top: -5px;
z-index: 0;
}
<div class="top">
<div class="gray-bar"></div>
<div class="cyan-bar"></div>
<div class="purple-bar"></div>
</div>
However, when I resize my window, at some point of time, the "cyan" triangle is causing issue because of the margins and the rotation. Therefore, I added some media queries to modify the rotation angle depending on the width of the screen but I feel that it's a bit "playing around" and that there is a better solution to achieve this.
I tried using borders to make the overlapping triangles but as it cannot be expressed as percentage, I'm a bit stuck. Indeed, the goal is that the result looks about the same whatever the user's screen resolution.
Is there a better solution than mine ?

Considering that the .top element uses the full viewport width, you can use viewport percentage units for the borders. This will make the triangles relative to the viewport width.
See this example with one div :
body,html{margin:0;padding:0;}
.topBar{
position:relative;
height:35px;
border-bottom:30px solid transparent;
border-right:100vw solid #B71E4C;
}
.topBar:before, .topBar:after{
content:'';
position:absolute;
top:0; left:0;
height:15px;
}
.topBar:before{
border-bottom:50px solid transparent;
border-left:100vw solid #2CA1AB;
}
.topBar:after{
border-bottom:40px solid transparent;
border-right:100vw solid #CDCBCC;
}
<div class="topBar"></div>

Maybe this help you, but, #web-tiki its the best solution, using pseudo-selectors: :before & :after
.top {
overflow: hidden;
height: 90px;
}
.top .gray-bar {
position: relative;
width: 100%;
height: 50px;
background-color:#cdcbcc;
-ms-transform: rotate(1.3deg);
transform: rotate(1.3deg);
margin-top:-35px;
z-index: 2;
}
.top .cyan-bar {
position: relative;
width: 150%;
height: 50px;
background-color:#2ca1ab;
-ms-transform: rotate(-2deg);
transform: rotate(-2deg);
z-index:1;
top: -5px;
margin-top:-30px;
margin-left:-100px;
}
.top .purple-bar {
position: relative;
width: 100%;
height: 20px;
background-color:#b71e4c;
-ms-transform: rotate(0.7deg);
transform: rotate(0.7deg);
margin-top: -20px;
z-index:0;
}
<div class="top">
<div class="gray-bar"></div>
<div class="cyan-bar"></div>
<div class="purple-bar"></div>
</div>

Related

Center a div more intelligently with CSS [duplicate]

This question already has answers here:
How to center a "position: absolute" element
(31 answers)
Closed 5 years ago.
I'm centering an object with the following code:
.object {
width: 70%;
height: 70%;
position: absolute;
top: 50%;
left:50%;
/* these are the lines to which I will refer */
margin-top: -350px;
margin-left: -350px;
}
I'm using margin top and left to subtract the half of the object size but that size is given as a percentage. So my question is there is a way to assign these margins So that I don't have to change them manually every time I change the box size?
To me, best option you have is to use the transform:translate property.
.object {
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
No need ta calculate the width/2 and height/2 margin anymore.
And if you're using SASS, here is a magic #mixin to use :
#mixin transform($transforms) {
-moz-transform: $transforms;
-o-transform: $transforms;
-ms-transform: $transforms;
-webkit-transform: $transforms;
transform: $transforms;
}
#mixin center($position: "both") {
position: absolute;
#if $position == "vertical" {
top: 50%;
#include transform(translateY(-50%));
}
#if $position == "horizontal" {
left: 50%;
#include transform(translateX(-50%));
}
#if $position == "both" {
top: 50%;
left: 50%;
#include transform(translate(-50%, -50%));
}
}
Then, simply use
.object {
// both vertical and horizontal
#include center;
// only vertical
#include center(vertical);
// only horizontal
#include center(horizontal);
}
One of the many ways - use transform property to center the element - see demo below:
.object {
width: 70%;
height: 70%;
position: absolute;
top: 50%;
left:50%;
border: 1px solid red;
transform:translate(-50%, -50%);
}
<div class="object">Two</div>
You should use flex.
HTML
<body>
<div class="square"></div>
</body>
CSS
body{
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.square{
width: 200px;
height: 200px;
background-color: red;
}
.main_div{
width:200px;
height:200px;
border:thin black solid;
position:relative;
}
.main_div .object {
width: 70%;
height: 70%;
position: absolute;
transform:translate(-50%, -50%);
top: 50%;
left:50%;
border: thin red solid;
}
<div class="main_div">
<div class="object">Object Div Text</div>
</div>
Hope this helps.
Why not use margin: 0 auto?
.object {
width: 70%;
height: 70%;
position: absolute;
top:0;
left:0;
right:0;
bottom:0;
margin:0 auto;
}
https://jsfiddle.net/p9hy06tg/4/

If I have two identical elements, one scaled to 2x, how scale down it's inner element and place it where it would be at 1x?

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

How to set ribbon on image by stacking it in a div?

I currently have an ng-repeat that looks like this:
<div class="repeaterDiv" data-ng-repeat="item in itemArray">
<div class="wrapper">
<img class="imageClass" ng-src="{{item.image}}"/>
<div class="corner-ribbon bottom-right sticky green shadow">Changed</div>
</div>
</div>
Here is the CSS pulled from this codePen:
.corner-ribbon{
width: 200px;
background: #e43;
position: absolute;
top: 25px;
left: -50px;
text-align: center;
line-height: 50px;
letter-spacing: 1px;
color: #f0f0f0;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.sticky{
position: fixed;
}
.corner-ribbon.shadow{
box-shadow: 0 0 3px rgba(0,0,0,.3);
}
.corner-ribbon.bottom-right{
top: auto;
right: -50px;
bottom: 25px;
left: auto;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.green{background: #2c7;}
I am trying to figure out how to get the ribbon to be restricted to the wrapper class. Does anyone know how I can do that? so I'm still using the same ribbon, but instead of being in the bottom right of the screen, it is at the bottom right of the image for which it applies?
you need to use relative/absolute position and reset display of .wrapper to shrink on image. Then add overflow:hidden to cut off edges of ribbon:
.corner-ribbon {
width: 200px;
background: #e43;
position: absolute;
top: 25px;
left: -50px;
text-align: center;
line-height: 50px;
letter-spacing: 1px;
color: #f0f0f0;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.sticky {
position: absolute;
}
.corner-ribbon.shadow {
box-shadow: 0 0 3px rgba(0, 0, 0, .3);
}
.corner-ribbon.bottom-right {
top: auto;
right: -50px;
bottom: 30px;
left: auto;
transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
}
.corner-ribbon.green {
background: #2c7;
}
.wrapper {
position: relative;
display: table-cell;/* or inline-block or float */
overflow: hidden;
}
img {
display: block;
}
<div class="repeaterDiv" data-ng-repeat="item in itemArray">
<div class="wrapper">
<img class="imageClass" ng-src="{{item.image}}" src="http://lorempixel.com/300/200" />
<div class="corner-ribbon bottom-right sticky green shadow">Changed</div>
</div>
</div>
The class has fixed positioning.
.corner-ribbon.sticky{
position: fixed;
}
So for exact css you may not be able to attach ribbon to each img, rather ribbon would go to specific place in window only. However, you can adjust css a bit. Make wrapper class relative, and .corner-ribbon.sticky absolute position. Then adjust your css fot top/bottom/left/right properties to align them.
.wrapper{
position: relative;
}
.wrapper .corner-ribbon.sticky{
position: absolute;
/* put top/bottom/left/right values here*/
}

Position small images in a circular array around large image

I am trying to find a clean way to float multiple image bubbles around a large image in a circular manner.
There will probably be no more than six bubbles per image, but I want to find a recursive and responsive way to position these bubbles around any sized parent image. These parent images will be equal height/width and no lower than 100px. (100 x 100, 130 x 130, ect..)
Not sure how to do this best while making it responsive to the screen size and supported on all main browsers. I also would prefer if this can be done with pure css/sass, and without an external library.
Code so far: http://jsfiddle.net/qatkr261/1/
HTML
<div id="body">
<div id="background">
<div class="company-container">
<img class="company" src="https://placeholdit.imgix.net/~text?txtsize=10&txt=120%C3%97120&w=120&h=120" />
<img src="https://placeholdit.imgix.net/~text?txtsize=10&txt=50%C3%9750&w=50&h=50" class="company-side-bubble" />
<img src="https://placeholdit.imgix.net/~text?txtsize=10&txt=50%C3%9750&w=50&h=50" class="company-side-bubble" />
<img src="https://placeholdit.imgix.net/~text?txtsize=10&txt=50%C3%9750&w=50&h=50" class="company-side-bubble" />
</div>
<div class="company-container">
<img class="company" src="https://placeholdit.imgix.net/~text?txtsize=10&txt=120%C3%97120&w=120&h=120" />
<img src="https://placeholdit.imgix.net/~text?txtsize=10&txt=50%C3%9750&w=50&h=50" class="company-side-bubble" />
<img src="https://placeholdit.imgix.net/~text?txtsize=10&txt=50%C3%9750&w=50&h=50" class="company-side-bubble" />
<img src="https://placeholdit.imgix.net/~text?txtsize=10&txt=50%C3%9750&w=50&h=50" class="company-side-bubble" />
</div>
</div>
</div>
CSS (#body and #background are just demo containers)
#body {
height:500px;
width:500px;
}
#background {
background:#F9F9F9;
}
.company-container {
display:inline-block;
padding:20px;
}
.company {
border-radius: 80px;
display: block;
height: 130px;
width: 130px;
margin: 15px auto;
background:#E5E5E5;
}
.company:hover {
transform: scale(1.2);
cursor:pointer;
}
.company-side-bubble {
border-radius: 30px;
width: 40px;
height: 40px;
position:absolute;
top:0;
border: solid 1px red;
}
.company-side-bubble:hover {
transform: scale(1.2);
cursor:pointer;
}
.company-side-bubble:nth-of-type(2) {
margin-top: 15px;
margin-left: 44px;
}
.company-side-bubble:nth-of-type(3) {
margin-top: 34px;
margin-left: 91px;
}
.company-side-bubble:nth-of-type(4) {
margin-left: 109px;
margin-top: 81px;
}
You can do that using percents instead of pixels as unit.
Also you will need to to use translateX and translateY to compensate for the small images width and height.
Here, i have done it for you: http://jsfiddle.net/qatkr261/2/
.company-side-bubble:nth-of-type(2) {
top: 0%;
left: 50%;
transform: translateX(-50%) translateY(25%);
}
.company-side-bubble:nth-of-type(3) {
top: 25%;
right: 25%;
transform: translateX(50%) translateY(-50%);
}
.company-side-bubble:nth-of-type(4) {
right: 0%;
top: 50%;
transform: translateX(-25%) translateY(-50%);
}
.company-side-bubble:nth-of-type(5) {
top: 75%;
right: 25%;
transform: translateX(50%) translateY(-50%);
}
.company-side-bubble:nth-of-type(6) {
bottom: 0%;
left: 50%;
transform: translateX(-50%) translateY(-25%);
}
.company-side-bubble:nth-of-type(7) {
bottom: 25%;
left: 25%;
transform: translateX(-50%) translateY(50%);
}
.company-side-bubble:nth-of-type(8) {
top: 50%;
left: 0%;
transform: translateX(25%) translateY(-50%);
}
.company-side-bubble:nth-of-type(9) {
top: 25%;
left: 25%;
transform: translateX(-50%) translateY(-50%);
}
I have altered also some css on other classes to make it work, most important: .company do not have top:0 anymore and it's margin now is uniform (all four sides equal) and have grown, .company-container lost padding (compensated by .company margin) and gained position:relative
UPDATE:
If you want the bubbles to spread as well you will need to make additional selector for each one as follows:
.company:hover ~ .company-side-bubble:nth-of-type(2) {
top: -5%;
}
.company:hover ~ .company-side-bubble:nth-of-type(3) {
top: 20%;
right: 20%;
}
.company:hover ~ .company-side-bubble:nth-of-type(4) {
right: -5%;
}
...

Creating a slopy element

I am trying to achieve this effect in my webpage..
The red box is where I will be placing a menu, I would like the bottom of the red box to be slanted. The section on the right of the slant needs to be transparent as there may be an image in the background where the grey color is.
The only thing I can come up with is to rotate the element but that would also rotate the contents of the element which I do not want.. Only the bottom bg of the red element (which will be a solid color) should be slanted.
you can do it like that, just highlighted the rotated part blue, that you see what happens ;)
you might have to play with the top: and left: values if you change the size
edit: added a small menu example (really small ^^)
jsfiddle link
here is the html part:
<div id="menucontainer">
<ul>
<li>some</li>
<li>menu</li>
<li>here</li>
</ul>
</div>
<div id="rotatedDiv">
</div>
<div id="background"></div>
and here the css part:
#menucontainer{
position: relative;
z-index: 100;
background: red;
height: 100px;
}
#menucontainer ul {
position: absolute;
bottom: 0px;
left: 30px;
}
#menucontainer li {
list-style: none;
margin-left: 10px;
background: #123;
display: inline-block;
}
#rotatedDiv {
z-index: 99;
background: blue;
position: absolute;
top: 14px;
left: -5px;
height: 90px;
width: 200%;
-moz-transform: rotate(-2deg);
-webkit-transform: rotate(-2deg);
-o-transform: rotate(-2deg);
-ms-transform: rotate(-2deg);
transform: rotate(-2deg);
}
#background {
background: green;
}
you might want to modify it in any way you can think of, but the main part should be clear i think ;)
You can do it with a transparent border:
html
<div class="bgone">
<div class="content">This is where the menu would go.</div>
</div>
<div class="bgtwo"></div>
css
.bgone {
height: 100px;
background: black;
position: relative;
}
.bgtwo {
height: 50px;
border-top: 100px solid black;
border-right: 1000px solid transparent;
}
.content {
position: absolute;
top: 10px;
left: 10px;
color: #FFF;
}