I'm trying to make a splash page on my website with 2 large buttons, each a right angled triangle, and both join by the longest side to create a square. Basically I'm looking to find out how to make non-rectangular buttons in css.
I have no idea if this is even possible though, and cannot find anything online explaining similar techniques for buttons which are not rectangular, and i'm not particularly skilled in css. A push in the right direction would be very helpful!
A very old (unanswered question) deserves an answer.
You could use a nested div element in which the parent has an overflow set to hidden, with the child element rotated.
Here is a basic example: (please note: jQuery only required for demo)
$('.tri').click(function() {
alert("triangle clicked!");
});
.wrap {
height: 200px;
width: 200px;
position: relative;
overflow: hidden;
margin: 2px auto;
}
.wrap .tri {
position: absolute;
height: 70%;
width: 70%;
background: tomato;
transform-origin: bottom left;
bottom: 0;
transition: all 0.6s;
left: 0;
cursor: pointer;
transform: rotate(45deg);
}
.wrap2 {
transform: rotate(180deg);
}
.wrap .tri:hover {
background: black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrap">
<div class="tri"></div>
</div>
<div class="wrap wrap2">
<div class="tri"></div>
</div>
Related
I've looked into this a fair bit but can't seem to find a good, solid answer to find how to make a responsive circle around a div element of variable height.
It's easy to make a simple responsive circle using vw units.
<div style="height:20vw; width:20vw"></div>
However, I'm looking to use a min-height of an element and have a circle around this div.
Another way to create a responsive circle is using something like the snippet below, but again I can't adapt this to work for a variable height (again, I can't use vh units as the div will change in height.
.square {
position: relative;
width: 10%;
background: gray;
border-radius: 50%;
}
.square:after {
content: "";
display: block;
padding-bottom: 100%;
}
.content {
position: absolute;
width: 100%;
height: 100%;
}
<div class="square">
<div class="content">
</div>
</div>
I am trying to create something like the below, where the circle will never cut into the corners of the div (with around a 10px padding). I personally was trying to avoid javascript and would have preferred a css only approach, but it seems it's unavoidable. Maybe the only solution is to use a jquery to calculate the height of the element in order to apply this to a wrapper element?
I was playing around with this:
.square {
position: absolute;
top: 50%;
display: inline-block;
left: 50%;
transform: translate(-50%, -50%);
min-height: 100px;
border-radius: 50%;
background: url('https://i.imgur.com/2dxaFs9_d.webp?maxwidth=640&shape=thumb&fidelity=medium');
background-size: 100% 100%;
padding: 20px;
}
.content {
width: 300px;
min-height: 100px;
background: tomato;
}
<div class="square">
<div class="content">
Hello!<br>
<br><br><br>This has a variable height but fixed width<br><br><br>Hello
</div>
</div>
Clip-path can easily do this if you consider solid coloration.
Resize the element and the circle will follow:
.box {
width: 200px;
height: 200px;
overflow: hidden;
resize: both;
background: blue;
box-shadow: 0 0 0 200vmax red;
clip-path: circle(71%);
margin: 100px auto;
}
<div class="box"></div>
Related question to understand the magic number 71%: clip-path:circle() radius doesn't seem to be calculated correctly
To use an image we can consider pseudo elements. You can also rely on calc() to add the offset:
.box {
width: 200px;=
resize: both;
clip-path: circle(calc(71% + 10px));
margin: 100px auto;
position: relative;
font-size:35px;
color:#fff;
}
/* the background layer */
.box::before {
content:"";
position: absolute;
z-index:-1;
top:0;
left:0;
right:0;
bottom:0;
background:blue;
}
/* the image layer */
.box::after {
content:"";
position: fixed; /* to make sure the image cover all the screen */
z-index:-2;
top:0;
bottom:0;
left:0;
right:0;
background:url(https://picsum.photos/id/1015/1000/1000) center/cover no-repeat;
}
<div class="box" contenteditable="true"> Edit this<br>text </div>
I tried my hardest to figure this out with pure css. Though the problem with css I could not figure out how to calculate the diameter of the circle based on the content div size; the length from top left corner to bottom right corner of the variable height div.
I'm not sure if can be done using the calc() css function.
But I did manage to do it with a little jquery (which could easily be changed to pure javascript if you are not using jquery).
See working resizable example below (follow my comments in code)
Note: If you are using internet explorer the resizable demo content div will not resize.
// circumscriber for variable size divs
function circumscriber() {
// for each variable size div on page
$(".variable-size").each(function() {
// get the variable size div content width and height
let width = $(this).outerWidth();
let height = $(this).outerHeight();
// get the diameter for our pefect circle based on content size
let diameter = Math.sqrt(width ** 2 + height ** 2);
// extra 15 pixel circle edge around variable size div
let edge = 15;
// add current circle size width css
$('.circle', this).css({
'width': (diameter + (edge * 2)) + 'px'
})
});
}
// run the circumscriber (you might wana do this on ready)
circumscriber();
// if the window is resized responsively
$(window).on('resize', function() {
circumscriber();
});
// for demo purpose to fire circumscriber when resizing content
// not needed for real thing
$('.content').on('input', function() {
this.style.height = "";
this.style.height = ( this.scrollHeight - 30 ) + "px";
circumscriber();
}).on('mouseup', function() {
circumscriber();
});
/* variable size container to be circumscribed by circle */
/* none of these styles are required, this just to center the variable size div in the window for demo purposes */
.variable-size {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* resizable text area for demo */
/* again not needed */
.variable-size .content {
padding: 15px;
background: #fff;
resize: both;
overflow: auto;
color: #000;
border: none;
width: 200px;
font-weight: bold;
}
.variable-size .content:focus {
outline: 0;
}
/* child circle div css */
.variable-size .circle {
position: absolute;
background-image: url('https://i.imgur.com/2dxaFs9_d.webp?maxwidth=640&shape=thumb&fidelity=medium');
background-position: center center;
z-index: -1;
border-radius: 50%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
transition: all 0.5s ease;
width: 0;
}
/* fast way to make circle height the same as current width */
.variable-size .circle:before {
display: block;
content: '';
width: 100%;
padding-top: 100%;
}
/* demo window css */
HTML,
BODY {
height: 100%;
min-height: 100%;
background: black;
position: relative;
font-family: "Lucida Console", Courier, monospace;
}
<div class="variable-size">
<textarea class="content" rows="1" placeholder="TYPE TEXT OR RESIZE ME ↘"></textarea>
<div class="circle"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
See jsfiddle here... https://jsfiddle.net/joshmoto/6d0zs7uq/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2 * Math.PI);
ctx.stroke();
Source: https://www.w3schools.com/
You could use flex display and insert empty flex-items around the inner div and use flex-basis to fix their width.
Try this
.square {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
min-height: 100px;
border-radius: 50%;
background: black;
background-size: 100% 100%;
padding: 20px;
}
.content {
width: 300px;
min-height: 100px;
background: tomato;
}
.emptyDiv {
flex-basis: 120px
}
<div class="square">
<div class="emptyDiv"></div>
<div class="content">
Hello!<br>
<br><br><br>This has a variable height but fixed width<br><br><br>Hello
</div>
<div class="emptyDiv"></div>
</div>
I'm working on site where I need to animate divs that move over a sibling and apply a mix-blend-mode. I'm working with a library that create 2 divs the wrap around the blending element. The library also adds a transform to the direct parent, which is now breaking the blending. I figured this might relate to a stacking issue, but no matter how many/where I add a transform3d(0,0,0 ) the blend is still broken.
Due to the constraints of the library, I can't do much about of the wrappers or that the background is a sibling of the outermost wrapper.
If you toggle the requiredParent2 transform, everything works (as stated, this transform is added by a required library).
Additionally there are siblings to the blending element (mixBorder, which prevents me from moving the blending to the requiredParents)
Fiddle also here: https://jsfiddle.net/hb7qaod6/5/
.bg,
.root,
.requiredParent1,
.requiredParent2 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.requiredParent2 {
transform: translate3d(0px, 2px, 0px);
}
.bg {
background-color: red;
}
.mix,
.mixBorder {
position: absolute;
top: 50%;
left: 50%;
width: 25%;
height: 25%;
}
.mix {
background-color: white;
mix-blend-mode: difference;
}
.mixBorder {
outline: white solid thick;
}
<div class="root">
<div class="bg"></div>
<div class="requiredParent1">
<div class="requiredParent2">
<div class="mix">
</div>
<div class="mixBorder">
</div>
</div>
</div>
Here's part of a design:
As you can see - its simply a button that is exactly positioned between the two divs. The code is simply:
<div class="uc-apply-widget1">
<div class="top">
</div>
<div class="bottom">
<a>Get Started</a>
</div>
</div>
.uc-apply-widget1
{
.top
{
background-color:#primary-color;
height:30rem;
}
.bottom
{
background-color:#primary-600;
padding:0 1.6rem 1.6rem 1.6rem;
a
{
margin-top:-2.8rem;
}
}
}
However, I've come across a problem with using negative margins. I expected to just be able to move the button outside of the bottom div by applying a half height negative margin. Although the button does move upwards, it doesn't move the full 2.8 rem - the amount of movement is the same even if I apply 50rem.
The other solution is to use position relative, which does move the button up, but does not drag the bottom div upwards with it.
So I'm looking to move the button up by n amount and reduce the bottom div height by n amount - any ideas - I may just be having a bad day.
use
position: absolute;
top: 0; left: 0;
transform: translateY(-50%);
on your button
https://developer.mozilla.org/en-US/docs/Web/CSS/transform
Here is one way of realizing your design.
Set the a element to have display: table and position: absolute with
top and left offsets to 0 and 50% respectively.
The display: table rule will give you a shrink-to-fit width, which may be what you need.
You can then use the CSS3 transform property to translate the element by -50% both in the X and the Y directions to get the centering.
The advantage here is that you don't have to specify the dimensions for the a element.
.uc-apply-widget1 {
width: 400px;
margin: 0 auto;
}
.top {
background-color: beige;
height: 10rem;
}
.bottom {
background-color: lightgray;
height: 5rem;
padding: 0 1.6rem 1.6rem 1.6rem;
position: relative;
}
a {
display: table;
width: auto;
margin: 0 auto;
padding: 10px;
border: 1px dotted blue;
position: absolute;
top: 0;
left: 50%;
transform: translateY(-50%) translateX(-50%);
}
<div class="uc-apply-widget1">
<div class="top">
</div>
<div class="bottom">
<a>Get Started</a>
</div>
</div>
Setup
I have three divs using CSS3 translations in all directions within a container div that is itself within an outer, fullscreen div. The outermost div, the full screen one, has perspective set on it.
HTML
<div class='outer'>
<div class='container ofhidden'>
<div class='item' id='item1'></div>
<div class='item' id='item2'></div>
<div class='item' id='item3'></div>
</div>
</div>
CSS
.outer {
perspective: 1000;
width: 100%;
height: 100%;
position: absolute;
overflow: hidden;
}
.outer .container {
background-color: grey;
width: 130%;
height: 100%;
padding: 1em;
}
.outer .container.ofhidden {
overflow: hidden;
}
.outer .container .item {
border: 1px solid black;
width: 50px;
height: 50px;
}
.outer .container .item#item1 {
background-color: green;
transform: translate3d(10px, 10px, -10px);
}
.outer .container .item#item2 {
background-color: goldenrod;
transform: translate3d(10px, 10px, 0);
}
.outer .container .item#item3 {
background-color: red;
transform: translate3d(10px, 10px, 10px);
}
Problem
The div that contains the translated elements has overflow: hidden; set on it which disables or ignores the translation in the Z direction while not effecting the other directions.
Demo
Please see this pen http://codepen.io/aaron/pen/Ihrxj for the code and a button which toggles overflow: hidden; to demonstrate the effect.
For those not familiar with HAML, SCSS/Compass, or CoffeeScript, you can click on the name of the preprocessor next to HTML, CSS, and JS to see the generated code in the codepen.
I don't know why this is happening, but i can suggest a couple of workarounds.
An obvious solution is to set overflow: hidden; (if you really need it) on items (either with .item or .container > *, instead of applying it to the container.
Another option is to position items absolutely. It's not very handy but it might work out for your layout (you can position items absolutely relatively to the container).
In both cases transform3d won't be disabled/ignored.
I am building a site that has an absolutely positioned banner at the top of the page. This div has a container with id showcase. Overlaying this banner is the navigation bar and logo, both of these are inside a container div called navLogoContainer, it is relatively positioned.
Both of these container divs are NOT children of any other elements (other than body and html), they are independent.
This is the weird part, if I put the navLogoContainer code ABOVE the code for the showcase, the contents of navLogoContainer are not shown, however one of the links is still clickable (the logo), but not visible, everything else (the navbar) is neither clickable or visible.
If I put the navBarContainer code BELLOW the showcase code, everything works perfectly.
Sure, I could just put the navBarContainer code bellow the showcase code and everything would be fine, but this results in my code not being as readable, and not following a logical order, which I would like to avoid. Plus, I'd really like to know when the heck it's doing this!
I'm really baffled by this, I've been trying opacities, display properties, z-indexes, everything I could think of, any help with this would be very much appreciated.
Thanks in advance.
The relevant HTML and CSS (apologies for the scruffiness of, and the comments all over the CSS, it's not yet at release quality :) :
HTML:
<div id="navLogoContainer">
<div id="logo">
<p class="big">Name</p>
<p class="small">Description</p>
</div>
<nav>
Home
Link One
Link Two
</nav>
</div>
<div id="showcase">
<!First showcase>
<div id="firstShowcase">
<div id="firstCaseStudyContainer">
<div id="firstCaseStudy3DContainer">
<div id="firstCaseStudy">
<p class="caseStudyTitle">Case Study Title</p>
<p class="caseStudyDescription">A brief description of relevant stuffView the site or view a second page.</p>
</div>
</div>
</div>
</div>
</div>
The CSS:
/*The code for the navbar*/
#navLogoContainer {
margin: 0px auto;
width: 1050px;
padding-top: 23px;
height: 62px;
z-index: 5;
min-width: 1050px;
}
#logo {
position: absolute;
float: left;
background-color: #00224d;
height: 62px;
width: 273px;
}
#logo a {
position: absolute;
display: block;
width: 100%;
height: 100%;
z-index: 3;
}
/*The showcase container*/
#showcase {
position: absolute;
width: 100% !important;
height: 399px;
top: 0px;
min-width: 1050px;
z-index: 0;
}
/*The backgrounds for the showcases*/
#firstShowcase {
background-image: url("first.png");
margin: 0;
width: 100% !important;
height: 100%;
z-index: 0;
}
/*The CONTAINERS for the case studies*/
#firstCaseStudyContainer {
width: 930px;
height: 399px;
margin: 0px auto;
z-index: 0;
}
/*The 3D containers*/
#firstCaseStudy3DContainer {
position: absolute;
height: 177px; /*Case study box height related. DO NOT SET TO AUTO. This value must be done by hand.*/
width: 410px;
margin-left: 530px;
margin-top: 247px;
background-image: url("3dtriangle.png");
background-position-y: 100%;
background-repeat: no-repeat;
-webkit-transition: all 0.6s;
-moz-transition: all 0.6s;
}
/*The actual text boxes for the case studies. They default to auto*/
#firstCaseStudy {
position: absolute;
height: auto;
width: 392px;
bottom: 0;
margin-left: 9px;
overflow-y: hidden;
-webkit-transition: all 1.0s;
-moz-transition: all 1.0s;
background-color: black;
overflow-y: hidden;
}
From what this says the showcase is doing exactly what you are telling it to do.
you put in the navLogoContainer which has no position, so it's going to be anchored to the top. Then you put in the showcase. This has an absolute position with a top: 0 so it's absolutely positioned to the top of either the page or the container element that both of these are in. So it makes sense that it's covering the logo. If you want the showcase below the logo stuff you need to position it below the navLogoContainer.
So if the navLogoContainer is 50px high the top attribute of the showcase should be 50px. If you're looking to have the navLogoContainer just be above the showcase then you need to give it a position:relative + some z-index love so it knows what it's doing.