Position the siblings when using scaling with transform property - javascript

I am implementing the CSS transform property over a division and have a use case of moving the siblings which are located next to it as per the scaling.
I tried adjusting the positions but did not work and thought this is how the transform functions. I might be wrong so want to give a one more try here.
.parent{
display:flex;
}
.childA{
padding: 1rem;
width: 20rem;
background: lightblue;
}
.childA:hover {
transform: scale(5);
transform-origin:top left;
z-index:0;
}
.childB {
border: solid 1px;
color:white;
padding: 1rem;
background: red;
z-index:1 /*Not sure why I had to do this too*/
}
<div class='parent'>
<div class='childA'>Child A scales</div>
<div class='childB'>I want to move when scaled</div>
</div>
Please take a look at this playground where the child element is just staying there but I need it to move towards the right
https://codepen.io/frank-underwood/pen/jOOmLJO?editors=1100

.parent{
display:flex;
}
.childA{
padding: 1rem;
width: 20rem;
background: lightblue;
}
.childA:hover {
transform: scale(5);
transform-origin:top left;
z-index:0;
}
.childA:hover + .childB {
transform: translateX(calc(22rem * 4));
}
.childB {
border: solid 1px;
color:white;
padding: 1rem;
background: red;
z-index:1
}
<div class='parent'>
<div class='childA'>Child A scales</div>
<div class='childB'>I want to move when scaled</div>
</div>
I'm not sure how much you're wanting to move it, or where.. Here is code to make it move on the hover of your scaling element. I'm using the adjacent CSS combinator to make this happen. When you're hovering ChildA, the adjacent ChildB can be given a set of properties.
As for why you had to put a z-index on .childB was because transforms create a new stacking context. Even though .childA comes before .childB in your HTML, the transform essentially brings .childA to a new layer. Therefore, you have to set .childB's z-index.
https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Positioning/Understanding_z_index/The_stacking_context
Here's some reading about stacking context. It's really important to understand how these work and what creates new ones.
edit You can calc the translate based off the element your hovering and it will consistently move. I added 2rem to the width because you have 1rem of padding on either side. 22rem * 4 instead of 5 because scale(1) = 22rem.

If you are able to adjust your html structure you can easily do this:
.parent{
display:flex;
}
.leftDiv{
background:yellow
}
.childA{
padding: 1rem;
background: lightblue;
position:relative;
}
.childA:hover {
transform: scale(2);
transform-origin:top left;
z-index:0;
}
.childA:hover .childB {
transform: scale(0.5);
transform-origin:top left;
}
.childB {
border: solid 1px;
color:white;
padding: 1rem;
background: red;
position:absolute;
left:100%;
top:0;
bottom:0;
white-space:nowrap;
}
<div class='parent'>
<div class='leftDiv'>I will just stay here</div>
<div class='childA'>Child A scales
<div class='childB'>I want to move when scaled</div>
</div>
</div>

Transform affect like absolute position, so you increase width and with calc method you can set how times it increas;
.parent{
display:flex;
}
.childA{
padding: 1rem;
width: 20rem;
background: lightblue;
}
.childA:hover {
width: calc(20rem * 5);/*here you can change 5*/
transform-origin:top left;
}
.childB {
border: solid 1px;
color:white;
padding: 1rem;
background: red;
}
<div class='parent'>
<div class='childA'>Child A scales</div>
<div class='childB'>I want to move when scaled</div>
</div>

Related

hover element below other element possibly hovered

I have a problem with my css.
i have some element generated by javascript and when i hover them i display another element but i don't know why, the new element displayed is below the others generated element...
this is my css about this problem:
.hiddenTextjob
{
display:none;
background-color:#000;
color:#FFF;
width:170px;
z-index:2!important;
height:55px;
}
.ghost_for:hover > .hiddenTextjob
{
display: block;
background-color:#000;
color:#FFF;
width:170px;
margin-top:-55px;
z-index:1!important;
}
.ghost_for
{
border: 0;
position:absolute;
background-color:blue;
z-index:1!important;
}
.hiddenTextjob is below ghost_for but he must be above...
Thanks by advance
[EDIT] here a jsfiddle to illustrate:
https://jsfiddle.net/95jtx2oL/
when you hover a blue element sometine the black hover is above sometime he is below that make me mad...
.ghost_for:hover {
z-index: 2!important;
}
The above code is enough to fix the issue ^^ jdfiddle
The issue was because of the stacking of HTML. The lower elements will be higher if they are on the same index. So if you can raise the z-index of the hovered element, it's child element will be higher as well.
It looks a bit strange that you set z-index to 1 here.
.ghost_for:hover > .hiddenTextjob
{
display: block;
background-color:#000;
color:#FFF;
width:170px;
margin-top:-55px;
z-index:1!important;
}
The initial value of 2 seems correct. Try to remove z-index from the above code or set it to 2.
I am unsure of your HTML but try this if it works for you:
.hiddenTextjob {
display: none;
background-color: #000;
color: #fff;
width: 170px;
z-index: 2 !important;
height: 55px;
}
.ghost_for:hover > .hiddenTextjob {
display: block;
background-color: #000;
color: #fff;
width: 170px;
margin-top: -55px;
}
.ghost_for {
border: 0;
position: absolute;
background-color: blue;
z-index: -1;
}

How to replicate a sliding search bar similar to the one on Petfinder

I try to create something similar to Petfinder search menu.
The problem I'm stuck with is that I can't figure out how to make a slide always appear just before the button(only covering it and not propogate to its borders when I change the size of the screen). When the slide search meets the 'heart' element it should act like it hits a wall and not going through it. So the search menu should appear before the button and replacing the previous content from the left side. I tried many options, included hiding this menu by setting width to 0 vw and heigt to 0 vh and positioning it fixed but it wasn't the case. Look at this picture. When I click the search button the menu appears but how to make it appear right from the button and not from the right edge of the screen as it does now? (see the code below)
The second question is how to incorporate this search to a css flow so it all will act as a flex element as a whole when the size of the screen changes? Because right now this slide not shrink when I change width of the screen.
But my search always gets one width. It gets confusing when the size of the screen gets smaller. It results in elements overlaying one another.
const slide = document.getElementById('slide');
let open = true;
document.getElementById('btn').addEventListener('click', (event) => {
if (open) {
slide.classList.add('show')
}
})
.parent {
background-color: #EEE;
font-family: sans-serif;
font-size: 20px;
padding: 25px;
margin: 0;
overflow: auto;
display: flex;
}
.first,
.second,
.third {
padding: 30px;
}
.first {
background-color: salmon;
flex-basis: 120px;
}
.second {
background-color: yellow;
flex-grow: 1
}
.third {
background-color: #56D7F7;
flex-grow: 1
}
.btn {
background-color: red;
cursor: pointer;
}
.slide {
display: flex;
transform: translateX(100%);
background-color: #FFE689;
top: 0;
position: relative;
transition: transform .3s
cubic-bezier(0, .52, 0, 1);
}
.show {
transform: translateX(80%);
}
<div class='parent'>
<div class='first'>1</div>
<div class='second'>2</div>
<div id='btn' class='btn'>Button</div>
<div class='third'>3</div>
</div>
<div id='slide' class='slide'>
Hello
</div>
The picture above shows how it should look like.
The code here is just for the sake of example, I am doing it on React but the problem is clear.
Well other than inspecting the elements on petfinder's website and deconstructing their styles, this is a rough version that I think performs as you are specifying.
const searchBar = document.querySelector('#search-bar');
const openBtn = document.querySelector('#open-btn');
const closeBtn = document.querySelector('#close-btn');
const brand = document.querySelector('#brand');
openBtn.addEventListener('click', (e) => toggleSlider() );
closeBtn.addEventListener('click', (e) => toggleSlider() );
function toggleSlider(){
searchBar.classList.toggle('open');
brand.classList.toggle('open');
}
.example{
max-width:600px;
margin:0 auto;
display:flex;
align-items:center;
justify-content:space-between;
}
.example .btns{
width:100px;
}
.slide-area{
width:100%;
padding:10px;
background-color: #fff;
display:flex;
align-items:center;
justify-content:space-between;
position: relative;
height:50px;
overflow:hidden;
}
.brand{
z-index:100;
transition:all 1s ease;
}
.brand.open{
color:white;
}
.search-bar{
display: flex;
justify-content:flex-end;
align-items:center;
background-color:purple;
position:absolute;
padding:10px;
right:0;
top:0;
left:0;
bottom:0;
transform: translateX(100%);
transition:all 1s ease;
}
.search-bar form{
display:flex;
justify-content:space-between;
align-content:center;
}
.search-bar input[type="text"]{
margin-left:10px;
}
.search-bar.open{
transform: translateX(0);
}
<header class="example">
<div class="slide-area">
<div id="brand" class="brand">Petfinder</div>
<nav>Menu Stuff</nav>
<button id="open-btn">Search</button>
<div id="search-bar" class="search-bar">
<label>Search:</label>
<form>
<input type="text"/>
<input type="submit" value="search"/>
</form>
<button id="close-btn">X</button>
</div>
</div>
<div class="btns">Heart</div>
<div class="btns">Sign up</div>
<div class="btns">Log in</div>
</header>

Reveal/slide image using clipaths

I am looking to create an animation that slide an image but not using the traditional slide CSS animations, this not achieve the result I am looking for, so basically the animation contains 2 images, the two images are similar (contains the same content as the same sizes) but colors are inverted.
The code I implemented only slide the image to left or right, I'd like to do the same animations but keeping the image in the same place, like when it slides it reveals the background image content as it progress but colors inverted.
I was thinking to apply the animation to clipath crop rather than actual image, below is a working jsfiddle of the issue I am facing.
$(".btn").click(function() {
$(".reveal").toggleClass("show");
})
html,
body {
background-color: #333;
color: #fff;
width: 100%;
height: 100%;
text-align: center
}
.reveal {
overflow: hidden;
position: relative;
display: inline-block;
}
.reveal:after {
content: " ";
position: absolute;
display: block;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('https://i.imgur.com/UBOmQ7T.jpg');
z-index: 2;
transition: all 2s ease;
}
.reveal.show:after {
left: 100%
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="reveal">
<img src='https://i.imgur.com/R6978y3.jpg' />
</div>
<br />
<button class="btn">Reveal!</button>
https://jsfiddle.net/v7fte3m8
You can do this with multiple background. The trick is to make background-clip of one of them to be content-box then adjust the padding to create the reveal effect:
.box {
width:300px;
height:200px;
box-sizing:border-box;
background:
url('https://i.imgur.com/UBOmQ7T.jpg'),
url('https://i.imgur.com/R6978y3.jpg');
background-clip:
content-box,
padding-box;
background-size:cover;
background-position:center;
transition:1s all;
padding-left:0;
}
.box:hover {
padding-left:300px;
}
<div class="box">
</div>
In case you will always have image with inverted colors you can consider the original image and the invert() filter:
.box {
width:300px;
height:200px;
box-sizing:border-box;
background:
url('https://i.imgur.com/R6978y3.jpg');
background-size:cover;
background-position:center;
}
.box:before {
content:"";
display:block;
height:100%;
background:inherit;
background-clip:content-box;
box-sizing:inherit;
transition:1s all;
padding-left:0;
filter:invert(1);
}
.box:hover:before {
padding-left:300px;
}
<div class="box">
</div>

Minimal (shortest) HTML for clickable "show-hide" text or spoiler

Yes, there are a zillion questions and pages explaining how to use html, css and (optionally) javascript to create similar things going by the names of:
hints
spoilers
toggles
show/hides
tooltips
But I haven't found an answer to this question:
Is it possible to create CSS to make something similar to this (a snippet of html as tiny as possible) behave as a toggle / spoiler when clicked?
<div class="hint">The answer starts with an A</div>
If it's not possible... That's okay! The question is about whether that's possible -- I just want to know.
I'm already aware of the barebones solution that works when hovered:
<div title="The answer starts with an A. (This is shown when hovered.)">
But the solution has to be clickable because it will be displayed on a phone, where "hovering" doesn't exist.
The CSS can be long, but the html has to be the shortest possible. The reason why the html must be barebones is that I will be typing it manually many times. I don't care whether it's a div or a span or what fields are specified, just as long as it's short.
There cannot be any other html anywhere as part of the solution. That is because in this system I have to type all the html every time, whereas I get the CSS for free.
It doesn't even have to be a real toggle: all I care about is that it starts out hidden and is shown when clicked.
Thanks in advance for your insights!
TL;DR:
Minimal CSS version for custom attribute tooltip (you can choose other name):
[tooltip]:active::after {
content: attr(tooltip);
}
<div tooltip="This is tooltip">some div</div>
More complex solution
You can create rules for custom attribute and add before (for tooltip's arrow) and after (for tooltip's body) pseudo elements.
Default opacity for preudo elements is set to 0. When element with custom attribute is active, set opacity to 1.
(Source: pure css tooltip tutorial)
div{
margin: 0.5em 15em;
}
[tooltip]{
position:relative;
display:inline-block;
}
[tooltip]::before {
content: "";
position: absolute;
top:-6px;
left:50%;
transform: translateX(-50%);
border-width: 4px 6px 0 6px;
border-style: solid;
border-color: rgba(0,0,0,0.7) transparent transparent transparent;
z-index: 99;
opacity:0;
}
[tooltip-position='left']::before{
left:0%;
top:50%;
margin-left:-12px;
transform:translatey(-50%) rotate(-90deg)
}
[tooltip-position='top']::before{
left:50%;
}
[tooltip-position='bottom']::before{
top:100%;
margin-top:8px;
transform: translateX(-50%) translatey(-100%) rotate(-180deg)
}
[tooltip-position='right']::before{
left:100%;
top:50%;
margin-left:1px;
transform:translatey(-50%) rotate(90deg)
}
[tooltip]::after {
content: attr(tooltip);
position: absolute;
left:50%;
top:-6px;
transform: translateX(-50%) translateY(-100%);
background: rgba(0,0,0,0.7);
text-align: center;
color: #fff;
padding:4px 2px;
font-size: 12px;
min-width: 80px;
pointer-events: none;
padding: 4px 4px;
z-index:99;
opacity:0;
}
[tooltip-position='left']::after{
left:0%;
top:50%;
margin-left:-8px;
transform: translateX(-100%) translateY(-50%);
}
[tooltip-position='top']::after{
left:50%;
}
[tooltip-position='bottom']::after{
top:100%;
margin-top:8px;
transform: translateX(-50%) translateY(0%);
}
[tooltip-position='right']::after{
left:100%;
top:50%;
margin-left:8px;
transform: translateX(0%) translateY(-50%);
}
[tooltip]:active::after,[tooltip]:active::before {
opacity:1
}
<div tooltip="This is left tooltip" tooltip-position="left">tooltip on left</div>
<div tooltip="This is right tooltip" tooltip-position="right">right tooltip</div>
<div tooltip="This is bottom tooltip" tooltip-position="bottom">bottom tooltip</div>
<div tooltip="This is tooltip">tooltip without position attribute</div>
If you're looking for a spoiler type thing with barely any code this might do it, and is pretty flexible.
.hint {
background-color: #ddd;
display: inline-block; /* you could do this as a full-width block instead */
padding: 8px 12px;
position: relative; /* needed for placeholder positioning */
}
.hint:not(:active) {
background-color: #eee; /* these two colors must be equivalent A */
color: #eee; /* these two colors must be equivalent B */
min-width: 96px; /* 72px if box-sizing is border-box; ensures the placeholder is fully visible if the text is smaller than the placeholder text */
user-select: none; /* if you want it to be copyable, may highlight spoiler text when they click */
}
.hint:not(:active)::before {
position: absolute;
top: 8px;
left: 12px;
content: 'Click\a0to\a0reveal'; /* non-breaking spaces probably necessary */
color: #999;
}
<div class="hint">I am a hint</div>
EDIT: added placeholder

Text moves down when using mouseover to show a span

Hey i have created a HTML file which is showing a span onmouseover with java script but the text which is under it is going down. I don't know how can i solve this problem.Please Help me Here is My Code with HTML,CSS and some javascript
<html><body><style>.Category{
background-color: rgb(77, 178, 236);
padding: 8px 12px;
width:10px;
height:500px;
margin:4px;
font-family: 'Roboto Condensed',sans-serif;
color: white !important;
z-index: 1;
}
.fblike
{
display: none;
position:relative;
top:-25px;
right:-600px;
width:20px;
}</style>
<div id="content"><div id="content1" onmouseover="document.getElementById('fblike').style.display = 'block';" onmouseout="document.getElementById('fblike').style.display = '';"><span class="Category">How TO</span> <span id="fblike" class="fblike">Utkarsh</span><br><br><div class="image">Utkarsh</div></div><hr>
</body></html>
If you position:absolute; your .fblike it won't disrupt flow of the other elements. Because it's position:relative; it will.
See the fiddle here: http://jsfiddle.net/A6afY/
.Category{
background-color: rgb(77, 178, 236);
padding: 8px 12px;
width:10px;
height:500px;
margin:4px;
font-family: 'Roboto Condensed',sans-serif;
color: white !important;
z-index: 1;
}
.fblike
{
display: none;
position:absolute;
/* commented so easier to show the fix
top:-25px;
right:-600px; */
width:20px;
}
#content1 {
/* absolute positioned elements must have positioned parents */
position: relative;
}
You need to position the .fblike class as absolute and then modify the top and right properties in the css to suit.
I have shown this here: http://jsfiddle.net/drfjy/
Use id #fblike instead class .fblike ,and change position absolute and set the top and left edge.
Try this code:
DEMO
#fblike
{
display: none;
position: absolute;
width: 20px;
top: 5px;
left: 100px;
}
You are trying style.display which won't consume space when the value is set to none.
If it is set to block the space will be consumed and it will be displayed.
You can try style.visibility for achieving what you need.

Categories