I'm trying to shift an element to the left by using transform. However, there is already an existing property on the style transform which looks like this: transform: translate3d(tx, ty, tz)
What I want to do is in addition of the translate3d(tx, ty, tz), I want to add another property called translateX(tx). So the whole style will look like this:
transform: translate3d(tx, ty, tz) translateX(tx)
Is there a way to do this in CSS? I don't want to overwrite the existing style property but add onto it.. My project is in Angular so would I have to do some code in the component end? Any help is greatly appreciated!
EDIT: I should also mention that the translate3d style is already defined for the element, not in my css file but by default (I'm using a library that sets the style for the element already). What I am trying to figure out is how to grab the current style, which is transform: translate3d AND add the translateX style to it as well so that it looks like:
transform: translate3d(tx, ty, tz) translateX(tx)
I will say it again, I do not set the translate3d in my own css file but it's a style that is automatically set for that specific element because of the library. If it helps, the library I am using is Leaflet for Angular
One quick and dirty way to achieve this effect would be to take advantage of relative positioning, using the following CSS properties:
position: relative
left: [tx]
Working Example:
.my-heading-a,
.my-heading-b {
position: relative;
transform: translate3d(40px, 20px, 10px);
}
.my-heading-a {
left: 0;
}
.my-heading-b {
left: 80px;
}
<h2 class="my-heading-a">My Heading A</h2>
<h2 class="my-heading-b">My Heading B</h2>
Update 2
No more custom variables. This example directly changes the translate3d's x value. Note: I mostly copied the getTransform function from another SO post.
const myEl = document.querySelector(".myElement");
const MOD = 10;
const getTransform = el => {
var transform = window.getComputedStyle(el, null).getPropertyValue('-webkit-transform');
var results = transform.match(/matrix(?:(3d)\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))(?:, (-{0,1}\d+)), -{0,1}\d+\)|\(-{0,1}\d+(?:, -{0,1}\d+)*(?:, (-{0,1}\d+))(?:, (-{0,1}\d+))\))/);
if (!results) return [0, 0, 0];
if (results[1] == '3d') return results.slice(2, 5);
results.push(0);
return results.slice(5, 8);
}
document.querySelector(".button").addEventListener("click", () => {
const [x, y, z] = getTransform(myEl);
const newX = parseInt(x, 10) + MOD;
myEl.style.transform = `translate3d(${newX}px, ${y}, ${z})`;
});
.myElement {
transform: translate3d(100px, 0, 0);
display: inline-block;
padding: 1rem;
background-color: tomato;
color: white;
transition: 0.3s transform;
}
.button {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: gray;
padding: .5rem 0;
color: white;
font-size: 1.4rem;
}
<div class="myElement">Test</div>
<button class="button">Move it</button>
Update
This will work and add 10px onto the initial x translation in the translate3d:
/* 200px + 10px = 210px x translation */
transform: translate3d(200px, 0, 0) translateX(10px);
div {
background-color: red;
padding: 1rem 2rem;
display: inline-block;
transform: translate3d(200px, 0, 0) translateX(10px);
}
<div></div>
Original Answer
Instead of this pattern…
transform: translate3d(tx, ty, tz) translateX(tx);
…you could set up the translate3d properties so they consume custom properties up front, and update the individual values as necessary.
transform: translate3d(var(--tx), var(--ty), var(--tz));
In the following example, I'm updating individual custom properties to move the box down and to the right. Note that nothing is overwritten and we have total control over the changes we'd like to make.
document.querySelector(".button").addEventListener("click", () => {
const style = document.documentElement.style;
style.setProperty("--tx", "120%");
style.setProperty("--ty", "80px");
});
:root {
--tx: 100%;
--ty: 40px;
--tz: 0;
}
.myElement {
transform: translate3d(var(--tx), var(--ty), var(--tz));
display: inline-block;
padding: 1rem;
background-color: tomato;
color: white;
transition: 0.3s transform;
}
.button {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: gray;
padding: .5rem 0;
color: white;
font-size: 1.4rem;
}
<div class="myElement">Test</div>
<button class="button">Move it</button>
Related
I am trying to make playing cards using CSS. I followed a YouTube video to make them and they were fine, but now I want to draw multiple cards next to each other, drawing 1 every time I click a button (I am trying to make Blackjack for a school project). The problem is that the cards will be placed under the previous one, and I have tried fiddling with it a bit and I think I have solved one of the issues but I have created another one. Let me show you.
Before, card-container had position absolute which is why i think was a problem, but now the bottom right number and suit is not even inside the container, also it still doesn't place the cards next to each other.
JavaScript that is executed when I click a button
I know that there is a bunch of stuff that there are other problems mainly in the JavaScript like the index of all getClassName, I know how to solve that, this is what I just cant figure out.
var cardcon = document.createElement('div');
cardcon.className = "card-container";
document.getElementById('gugu').appendChild(cardcon);
//
var card = document.createElement('div');
card.className = "card";
document.getElementsByClassName('card-container')[0].appendChild(card);
//
var valuecon = document.createElement('div');
valuecon.className = "value-container container-top";
document.getElementsByClassName('card')[0].appendChild(valuecon);
//
var valuenumber = document.createElement('div');
valuenumber.className = "value-number";
valuenumber.textContent = "7";
document.getElementsByClassName('value-container container-top')[0].appendChild(valuenumber);
//
var valuesuit = document.createElement("div");
valuesuit.className = "value-suit";
valuesuit.innerHTML = "♥";
document.getElementsByClassName('value-number')[0].appendChild(valuesuit);
//
var valuedon = document.createElement("div");
valuedon.className = "value-container container-bottom";
document.getElementsByClassName('card')[0].appendChild(valuedon);
//
var valuenumber1 = document.createElement('div');
valuenumber1.className = "value-number";
valuenumber1.textContent = "7";
document.getElementsByClassName('value-container container-bottom')[0].appendChild(valuenumber1);
//
var valuesuit1 = document.createElement("div");
valuesuit1.className = "value-suit";
valuesuit1.innerHTML = "♥";
document.getElementsByClassName('value-number')[1].appendChild(valuesuit1);
.card-container {
position: relative;
}
.card {
width: 250px;
height: 350px;
border: 3.5px solid gray;
border-radius: 12.5px;
box-shadow: 10px 10px grey;
background-color: white;
}
.value-container {
position: absolute;
}
.value-number {
font-family: 'Abel', sans-serif;
font-size: 30px;
}
.value-suit {
font-size: 30px;
}
.container-bottom {
bottom: 8px;
right: 16px;
transform: rotate(180deg);
}
.container-top {
top: 20px;
left: 20px;
}
.grid-container {
display: grid;
grid-template-columns: auto auto auto auto;
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
<div id="gugu" class="grid-container"></div>
I have changed this part of your css to put down number inside your card
.card-container {width:250px;}
.card {width:100%;}
var cardcon = document.createElement('div');
cardcon.className = "card-container";
document.getElementById('gugu').appendChild(cardcon);
//
var card = document.createElement('div');
card.className = "card";
document.getElementsByClassName('card-container')[0].appendChild(card);
//
var valuecon = document.createElement('div');
valuecon.className = "value-container container-top";
document.getElementsByClassName('card')[0].appendChild(valuecon);
//
var valuenumber = document.createElement('div');
valuenumber.className = "value-number";
valuenumber.textContent = "7";
document.getElementsByClassName('value-container container-top')[0].appendChild(valuenumber);
//
var valuesuit = document.createElement("div");
valuesuit.className = "value-suit";
valuesuit.innerHTML = "♥";
document.getElementsByClassName('value-number')[0].appendChild(valuesuit);
//
var valuedon = document.createElement("div");
valuedon.className = "value-container container-bottom";
document.getElementsByClassName('card')[0].appendChild(valuedon);
//
var valuenumber1 = document.createElement('div');
valuenumber1.className = "value-number";
valuenumber1.textContent = "7";
document.getElementsByClassName('value-container container-bottom')[0].appendChild(valuenumber1);
//
var valuesuit1 = document.createElement("div");
valuesuit1.className = "value-suit";
valuesuit1.innerHTML = "♥";
document.getElementsByClassName('value-number')[1].appendChild(valuesuit1);
.card-container {
position: relative;
width:250px;
}
.card {
width:100%;
height:350px;
border:3.5px solid gray;
border-radius: 12.5px;
box-shadow: 10px 10px grey;
background-color: white;
}
.value-container {
position: absolute;
}
.value-number {
font-family: 'Abel', sans-serif;
font-size: 30px;
}
.value-suit{
font-size: 30px;
}
.container-bottom{
bottom: 8px;
right: 16px;
transform: rotate(180deg);
}
.container-top{
top:20px;
left:20px;
}
.grid-container {
display: grid;
grid-template-columns: auto auto auto auto;
grid-gap: 10px;
background-color: #2196F3;
padding: 10px;
}
<div id="gugu" class="grid-container">
</div>
I'm not sure if I understand your problem but this is my solution.
to card-container add {display : flex}.
&& to card add {position : relative} (this is to fix the numbers floating out of the card)
Use an Inline-Block
<div> tags use by default the css property display:block;. This means that they will automatically claim the entire row that you place them on. The simplest solution is to use an object with the display:inline-block; property. Inline-blocks have all of the same other properties as a block element, but there is no automatic line-break that happens after it. So, if you got your code working right in all other respects using <div>s doing this will fix your problem without having to get messy trying to manipulate your position attributes at all.
To really simplify your code, just use <span> tags instead of <div> tags for your cards since these are inline-blocks by default.
How can I position several <img> elements into a circle around another and have those elements all be clickable links as well? I want it to look like the picture below, but I have no idea how to achieve that effect.
Is this even possible?
2020 solution
Here's a more modern solution I use these days.
I start off by generating the HTML starting from an array of images. Whether the HTML is generated using PHP, JS, some HTML preprocessor, whatever... this matters less as the basic idea behind is the same.
Here's the Pug code that would do this:
//- start with an array of images, described by url and alt text
- let imgs = [
- {
- src: 'image_url.jpg',
- alt: 'image alt text'
- } /* and so on, add more images here */
- ];
- let n_imgs = imgs.length;
- let has_mid = 1; /* 0 if there's no item in the middle, 1 otherwise */
- let m = n_imgs - has_mid; /* how many are ON the circle */
- let tan = Math.tan(Math.PI/m); /* tangent of half the base angle */
.container(style=`--m: ${m}; --tan: ${+tan.toFixed(2)}`)
- for(let i = 0; i < n_imgs; i++)
a(href='#' style=i - has_mid >= 0 ? `--i: ${i}` : null)
img(src=imgs[i].src alt=imgs[i].alt)
The generated HTML looks as follows (and yes, you can write the HTML manually too, but it's going to be a pain to make changes afterwards):
<div class="container" style="--m: 8; --tan: 0.41">
<a href='#'>
<img src="image_mid.jpg" alt="alt text"/>
</a>
<a style="--i: 1">
<img src="first_img_on_circle.jpg" alt="alt text"/>
</a>
<!-- the rest of those placed on the circle -->
</div>
In the CSS, we decide on a size for the images, let's say 8em. The --m items are positioned on a circle and it's if they're in the middle of the edges of a polygon of --m edges, all of which are tangent to the circle.
If you have a hard time picturing that, you can play with this interactive demo which constructs the incircle and circumcircle for various polygons whose number of edges you pick by dragging the slider.
This tells us that the size of the container must be twice the radius of the circle plus twice half the size of the images.
We don't yet know the radius, but we can compute it if we know the number of edges (and therefore the tangent of half the base angle, precomputed and set as a custom property --tan) and the polygon edge. We probably want the polygon edge to be a least the size of the images, but how much we leave on the sides is arbitrary. Let's say we have half the image size on each side, so the polygon edge is twice the image size. This gives us the following CSS:
.container {
--d: 6.5em; /* image size */
--rel: 1; /* how much extra space we want between images, 1 = one image size */
--r: calc(.5*(1 + var(--rel))*var(--d)/var(--tan)); /* circle radius */
--s: calc(2*var(--r) + var(--d)); /* container size */
position: relative;
width: var(--s); height: var(--s);
background: silver /* to show images perfectly fit in container */
}
.container a {
position: absolute;
top: 50%; left: 50%;
margin: calc(-.5*var(--d));
width: var(--d); height: var(--d);
--az: calc(var(--i)*1turn/var(--m));
transform:
rotate(var(--az))
translate(var(--r))
rotate(calc(-1*var(--az)))
}
img { max-width: 100% }
See the old solution for an explanation of how the transform chain works.
This way, adding or removing an image from the array of images automatically arranges the new number of images on a circle such that they're equally spaced out and also adjusts the size of the container. You can test this in this demo.
OLD solution (preserved for historical reasons)
Yes, it is very much possible and very simple using just CSS. You just need to have clear in mind the angles at which you want the links with the images (I've added a piece of code at the end just for showing the angles whenever you hover one of them).
You first need a wrapper. I set its diameter to be 24em (width: 24em; height: 24em; does that), you can set it to whatever you want. You give it position: relative;.
You then position your links with the images in the center of that wrapper, both horizontally and vertically. You do that by setting position: absolute; and then top: 50%; left: 50%; and margin: -2em; (where 2em is half the width of the link with the image, which I've set to be 4em - again, you can change it to whatever you wish, but don't forget to change the margin in that case).
You then decide on the angles at which you want to have your links with the images and you add a class deg{desired_angle} (for example deg0 or deg45 or whatever). Then for each such class you apply chained CSS transforms, like this:
.deg{desired_angle} {
transform: rotate({desired_angle}) translate(12em) rotate(-{desired_angle});
}
where you replace {desired_angle} with 0, 45, and so on...
The first rotate transform rotates the object and its axes, the translate transform translates the object along the rotated X axis and the second rotate transform brings back the object into position.
The advantage of this method is that it is flexible. You can add new images at different angles without altering the current structure.
CODE SNIPPET
.circle-container {
position: relative;
width: 24em;
height: 24em;
padding: 2.8em;
/*2.8em = 2em*1.4 (2em = half the width of a link with img, 1.4 = sqrt(2))*/
border: dashed 1px;
border-radius: 50%;
margin: 1.75em auto 0;
}
.circle-container a {
display: block;
position: absolute;
top: 50%; left: 50%;
width: 4em; height: 4em;
margin: -2em;
}
.circle-container img { display: block; width: 100%; }
.deg0 { transform: translate(12em); } /* 12em = half the width of the wrapper */
.deg45 { transform: rotate(45deg) translate(12em) rotate(-45deg); }
.deg135 { transform: rotate(135deg) translate(12em) rotate(-135deg); }
.deg180 { transform: translate(-12em); }
.deg225 { transform: rotate(225deg) translate(12em) rotate(-225deg); }
.deg315 { transform: rotate(315deg) translate(12em) rotate(-315deg); }
<div class='circle-container'>
<a href='#' class='center'><img src='image.jpg'></a>
<a href='#' class='deg0'><img src='image.jpg'></a>
<a href='#' class='deg45'><img src='image.jpg'></a>
<a href='#' class='deg135'><img src='image.jpg'></a>
<a href='#' class='deg180'><img src='image.jpg'></a>
<a href='#' class='deg225'><img src='image.jpg'></a>
<a href='#' class='deg315'><img src='image.jpg'></a>
</div>
Also, you could further simplify the HTML by using background images for the links instead of using img tags.
EDIT: example with fallback for IE8 and older (tested in IE8 and IE7)
Here is the easy solution without absolute positioning:
.container .row {
margin: 20px;
text-align: center;
}
.container .row img {
margin: 0 20px;
}
<div class="container">
<div class="row">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
</div>
<div class="row">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
</div>
<div class="row">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
<img src="https://ssl.gstatic.com/s2/oz/images/faviconr2.ico" alt="" width="64" height="64">
</div>
</div>
http://jsfiddle.net/mD6H6/
Using the solution proposed by #Ana:
transform: rotate(${angle}deg) translate(${radius}px) rotate(-${angle}deg)
I created the following jsFiddle that places circles dynamically using plain JavaScript (jQuery version also available).
The way it works is rather simple:
document.querySelectorAll( '.ciclegraph' ).forEach( ( ciclegraph )=>{
let circles = ciclegraph.querySelectorAll( '.circle' )
let angle = 360-90, dangle = 360 / circles.length
for( let i = 0; i < circles.length; ++i ){
let circle = circles[i]
angle += dangle
circle.style.transform = `rotate(${angle}deg) translate(${ciclegraph.clientWidth / 2}px) rotate(-${angle}deg)`
}
})
.ciclegraph {
position: relative;
width: 500px;
height: 500px;
margin: calc(100px / 2 + 0px);
}
.ciclegraph:before {
content: "";
position: absolute;
top: 0; left: 0;
border: 2px solid teal;
width: calc( 100% - 2px * 2);
height: calc( 100% - 2px * 2 );
border-radius: 50%;
}
.ciclegraph .circle {
position: absolute;
top: 50%; left: 50%;
width: 100px;
height: 100px;
margin: calc( -100px / 2 );
background: teal;
border-radius: 50%;
}
<div class="ciclegraph">
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
<div class="circle"></div>
</div>
Building off #Ana's excellent answer, I created this dynamic version that allows you to add and remove elements from the DOM and maintain proportionate spacing between the elements - check out my fiddle: https://jsfiddle.net/skwidbreth/q59s90oy/
var list = $("#list");
var updateLayout = function(listItems) {
for (var i = 0; i < listItems.length; i++) {
var offsetAngle = 360 / listItems.length;
var rotateAngle = offsetAngle * i;
$(listItems[i]).css("transform", "rotate(" + rotateAngle + "deg) translate(0, -200px) rotate(-" + rotateAngle + "deg)")
};
};
$(document).on("click", "#add-item", function() {
var listItem = $("<li class='list-item'>Things go here<button class='remove-item'>Remove</button></li>");
list.append(listItem);
var listItems = $(".list-item");
updateLayout(listItems);
});
$(document).on("click", ".remove-item", function() {
$(this).parent().remove();
var listItems = $(".list-item");
updateLayout(listItems);
});
#list {
background-color: blue;
height: 400px;
width: 400px;
border-radius: 50%;
position: relative;
}
.list-item {
list-style: none;
background-color: red;
height: 50px;
width: 50px;
position: absolute;
top: 50%;
left: 50%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<ul id="list"></ul>
<button id="add-item">Add item</button>
Here is a version I made in React from the examples here.
CodeSandbox Example
import React, { useRef, useEffect } from "react";
import "./styles.css";
export default function App() {
const graph = useRef(null);
useEffect(() => {
const ciclegraph = graph.current;
const circleElements = ciclegraph.childNodes;
let angle = 360 - 90;
let dangle = 360 / circleElements.length;
for (let i = 0; i < circleElements.length; i++) {
let circle = circleElements[i];
angle += dangle;
circle.style.transform = `rotate(${angle}deg) translate(${ciclegraph.clientWidth /
2}px) rotate(-${angle}deg)`;
}
}, []);
return (
<div className="App">
<div className="ciclegraph" ref={graph}>
<div className="circle" />
<div className="circle" />
<div className="circle" />
<div className="circle" />
<div className="circle" />
<div className="circle" />
</div>
</div>
);
}
You can certainly do it with pure css or use JavaScript. My suggestion:
If you already know that the images number will never change just calculate your styles and go with plain css (pros: better performances, very reliable)
If the number can vary either dynamically in your app or just may vary in the future go with a Js solution (pros: more future-proof)
I had a similar job to do, so I created a script and open sourced it here on Github for anyone who might need it. It just accepts some configuration values and simply outputs the CSS code you need.
If you want to go for the Js solution here's a simple pointer that can be useful to you. Using this html as a starting point being #box the container and .dot the image/div in the middle you want all your other images around:
Starting html:
<div id="box">
<div class="dot"></div>
<img src="my-img.jpg">
<!-- all the other images you need-->
</div>
Starting Css:
#box{
width: 400px;
height: 400px;
position: relative;
border-radius: 100%;
border: 1px solid teal;
}
.dot{
position: absolute;
border-radius: 100%;
width: 40px;
height: 40px;
left: 50%;
top: 50%;
margin-left: -20px;
margin-top: -20px;
background: rebeccapurple;
}
img{
width: 40px;
height: 40px;
position: absolute;
}
You can create a quick function along these lines:
var circle = document.getElementById('box'),
imgs = document.getElementsByTagName('img'),
total = imgs.length,
coords = {},
diam, radius1, radius2, imgW;
// get circle diameter
// getBoundingClientRect outputs the actual px AFTER transform
// using getComputedStyle does the job as we want
diam = parseInt( window.getComputedStyle(circle).getPropertyValue('width') ),
radius = diam/2,
imgW = imgs[0].getBoundingClientRect().width,
// get the dimensions of the inner circle we want the images to align to
radius2 = radius - imgW
var i,
alpha = Math.PI / 2,
len = imgs.length,
corner = 2 * Math.PI / total;
// loop over the images and assign the correct css props
for ( i = 0 ; i < total; i++ ){
imgs[i].style.left = parseInt( ( radius - imgW / 2 ) + ( radius2 * Math.cos( alpha ) ) ) + 'px'
imgs[i].style.top = parseInt( ( radius - imgW / 2 ) - ( radius2 * Math.sin( alpha ) ) ) + 'px'
alpha = alpha - corner;
}
You can see a live example here
There is no way to magically place clickable items in a circle around another element with CSS.
The way how I would do this is by using a container with position:relative;. And then place all the elements with position:absolute; and using top and left to target it's place.
Even though you haven't placed jquery in your tags it might be best to use jQuery / javascript for this.
First step is placing your center image perfectly in the center of the container using position:relative;.
#centerImage {
position:absolute;
top:50%;
left:50%;
width:200px;
height:200px;
margin: -100px 0 0 -100px;
}
After that you can place the other elements around it by using an offset() of the centerImage minus the offset() of the container. Giving you the exact top and left of the image.
var left = $('#centerImage').offset().left - $('#centerImage').parent().offset().left;
var top = $('#centerImage').offset().top - $('#centerImage').parent().offset().top;
$('#surroundingElement1').css({
'left': left - 50,
'top': top - 50
});
$('#surroundingElement2').css({
'left': left - 50,
'top': top
});
$('#surroundingElement3').css({
'left': left - 50,
'top': top + 50
});
What I've done here is placing the elements relative to the centerImage. Hope this helps.
You could do it like this: fiddle
Don't mind the positioning, its a quick example
The first step is to have 6 long columnar boxes:
The second step is to use position: absolute and move them all into the middle of your container:
And now rotate them around the pivot point located at the bottom center. Use :nth-child to vary rotation angles:
div {
transform-origin: bottom center;
#for $n from 0 through 7 {
&:nth-child(#{$n}) {
rotate: (360deg / 6) * $n;
}
}
Now all you have to do is to locate your images at the far end of every column, and compensate the rotation with an anti-rotation :)
Full source:
<div class="flower">
<div class="petal">1</div>
<div class="petal">2</div>
<div class="petal">3</div>
<div class="petal">4</div>
<div class="petal">5</div>
<div class="petal">6</div>
</div>
.flower {
width: 300px;
height: 300px;
// We need a relative position
// so that children can have "position:abolute"
position: relative;
.petal {
// Make sure petals are visible
border: 1px solid #999;
// Position them all in one point
position: absolute; top: 0; left: 50%;
display: inline-block;
width: 30px; height: 150px;
// Rotation
transform-origin: bottom center;
#for $n from 0 through 7 {
&:nth-child(#{$n}) {
// Petal rotation
$angle: (360deg / 6) * $n;
rotate: $angle;
// Icon anti-rotation
.icon { rotate: -$angle; }
}
}
}
}
See CodePen
On my page I want elements that will serve as horizontal "breaks" in the same way as hr elements, but I would like them to be shaped like a sine function.
Is that possible? If so, how?
Here's a fiddle for you to complete: http://jsfiddle.net/pdov7u85/
HTML:
<p>Here's some red text</p>
<!--some element with id someElement will go here-->
<p>Here's some blue text, which should be divided from the red text with a wavy line</p>
CSS:
p:nth-of-type(1)
{
color: red;
}
#someElement
{
}
p:nth-of-type(2)
{
color: blue;
}
Challenge accepted.
.sine {
text-align: center;
}
.sine_span {
display: inline-block;
margin:0;
padding:0;
height: 20px;
width: 40px;
border: 1px solid black;
}
.sine_span_first {
border-bottom: none;
border-radius: 20px 20px 0 0;
transform: translate(-20px, 0) scale(2,1);
}
.sine_span_second {
border-top: none;
border-radius: 0 0 20px 20px;
transform: translate(20px, 20px) scale(2,1);
}
.sine_span_first_2 {
transform: translate(0, 20px) scale(1,2);
}
.sine_span_second_2 {
transform: translate(0, 60px) scale(1,2);
}
Flat curve
<div class="sine">
<span class="sine_span sine_span_first"></span><span class="sine_span sine_span_second"></span>
</div>
<br />
Sharp curve
<div class="sine">
<span class="sine_span sine_span_first sine_span_first_2"></span><span class="sine_span sine_span_second sine_span_second_2"></span>
</div>
Btw, shouldn't you use some gif image for this?
You could draw that sine function in javascript:
var canvas = document.getElementById("canvas");
if (canvas == null || !canvas.getContext) {
return;
}
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "rgb(11,153,11)";
for (var i = 0; i <= 1000; i++) {
var x = i * 5;
var y = Math.sin(5 * x + 1);
ctx.lineTo(0.5 + x, 25 - y * 24);
}
ctx.stroke();
JSFiddle
Or you could just use an SVG image like Paulie_D suggested.
As #Paulie_D said don't over think it.
Be semantic and use a HR, give it a height and a background image.
hr{
border:none;
height:82px;
background:url('http://i60.tinypic.com/df8y75.png');
background-size:50%;
}
eg.
http://jsfiddle.net/pdov7u85/3/
note: background-size is not supported in older versions of IE but I only used it for convenience.
Can I customize
<input type='number'>
field to show all the time it's arrows? By default it's hidden till the field is has no focus. Below is what I'm talking about.
Firefox and IE don't have such behavior. So, I assume you are working with Google Chrome.
input::-webkit-inner-spin-button {
opacity: 1;
}
FYI. UA stylesheet has the following:
input::-webkit-inner-spin-button {
...
opacity: 0;
pointer-events: none;
}
input:enabled:read-write:-webkit-any(:focus,:hover)::-webkit-inner-spin-button {
opacity: 1;
pointer-events: auto;
}
html.css
The UI and behavior of <input type='number'>, as well as all the other HTML5 input types (e.g., type='date', etc), is browser and/or system dependent. To make the arrows always visible, you'd need to use a custom JS solution.
Only way that I can think of is... Having two buttons for incrementing and decrementing your input and using JS. You won't be using type="number" here since the JS will be incrementing and decrementing the number for you.
Here is an example, as mentioned here:
CSS:
.spin {
display: inline-block;
}
.spin span {
display: inline-block;
width: 20px;
height: 22px;
text-align: center;
padding-top: 2px;
background: #fff;
border: 1px solid #aaa;
border-radius: 0 4px 4px 0;
cursor: pointer;
}
.spin span:first-child {
border-radius: 4px 0 0 4px;
}
.spin input {
width: 40px;
height: 20px;
text-align: center;
font-weight: bold;
}
JS:
var spins = document.getElementsByClassName("spin");
for (var i = 0, len = spins.length; i < len; i++) {
var spin = spins[i],
span = spin.getElementsByTagName("span"),
input = spin.getElementsByTagName("input")[0];
input.onchange = function() { input.value = +input.value || 0; };
span[0].onclick = function() { input.value = Math.max(0, input.value - 1); };
span[1].onclick = function() { input.value -= -1; };
}
Note: Change background: #fff; to change the arrow colors. There are other neat examples available on the web as well!
Demo
I am using cesium : http://cesiumjs.org/
and I wanted to make some divs float over a cesium map, but I can't get it to work.
I tried the following container/tag method at jsfiddle.net/j08691/dChUR/5/ - substituing the image by a cesium map div - but it doesn't seem to work - the "tag" div isn't shown.
Any help?
You need to add position: absolute; and either top or bottom to your CSS, because the widget also uses absolute positioning. Adding this creates a new stacking context, which overrides z-index.
Here's a working example, hit "Run Code Snippet" at the bottom of this:
Cesium.Camera.DEFAULT_VIEW_FACTOR = 0;
var viewer = new Cesium.Viewer('cesiumContainer', {
timeline: false,
animation: false,
navigationHelpButton: false
});
var skyAtmosphere = viewer.scene.skyAtmosphere;
var skyCheckbox = document.getElementById('skyCheckbox');
skyCheckbox.addEventListener('change', function() {
viewer.scene.skyAtmosphere = skyCheckbox.checked ? skyAtmosphere : undefined;
}, false);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
font-family: sans-serif; color: #edffff;
}
#controlPanel {
position: absolute;
top: 5px;
left: 5px;
background: rgba(42, 42, 42, 0.8);
padding: 5px 8px;
border-radius: 5px;
}
label {
cursor: pointer;
}
label:hover span {
text-decoration: underline;
}
<link href="http://cesiumjs.org/releases/1.15/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.15/Build/Cesium/Cesium.js">
</script>
<div id="cesiumContainer"></div>
<div id="controlPanel">
This is a floating control panel<br/>
with a translucent background color.
<p>
<label>
<input id="skyCheckbox" type="checkbox" checked />
<span>Enable atmospheric effect</span>
</label><br/>
<button class="cesium-button">Button 1</button>
<button class="cesium-button">Button 2</button>
</p>
</div>
To add to emackey's answer, what I had to do in addition to adding position: absolute to my css was to add a top:150px or bottom:150px. Basically anything that will specify a position relative to the parent container.
Even though using the absolute position it is most likely being pushed down by the cesium widget since it takes up 100% height.