This question has probably been asked many times, I tried all suggestions and answers I could find on SO with no success.
What I am trying to achieve is a set of boxes (divs) layed out as follow:
The order does not really matter as long as there is no empty space between these boxes.
Here is what I have:
<div class="MyList">
<div class="ListItem" style="height:75px;"><span>Box 1</span></div>
<div class="ListItem" style="height:65px;"><span>Box 2</span></div>
<div class="ListItem" style="height:45px;"><span>Box 3</span></div>
<div class="ListItem" style="height:85px;"><span>Box 4</span></div>
<div class="ListItem" style="height:25px;"><span>Box 5</span></div>
</div>
and
.MyList
{
overflow:auto;
background:lightgray;
width:240px;
}
.ListItem {
color: #000;
background: white;
border: 1px solid grey;
min-height: 2em;
width: 100px;
padding: 0.5em 0.5em 0em 0.5em;
border-radius: 3px;
float: left;
cursor: pointer;
}
And here is the result (fiddle):
So far, I could get this:
I can't:
Use css column attribute as it is not supported in IE :(
Use javascript (Columnizer) to split my divs into two sets.
This is because I am turning these tiles into draggables and the javascript code
considerably hinders the usability of my application.
I can't use special selectors for left and right boxes as the list of boxes is dynamic (knockout generated)
Is this even achievable?
.leftBoxes
{
display: inline;
float: left;
width: 49%;
}
.rightBoxes
{
display: inline;
float: right;
width: 49%;
}
#box1
{
height: 100px;
}
#box2
{
height: 20px;
}
Create two floating to the left <divs>s as a columns (no "column" property), and put boxes in them in desired order.
<div class="MylistPart">
<div>
<div class="ListItem" style="height:75px;"><span>Box 1</span></div>
<div class="ListItem" style="height:65px;"><span>Box 2</span></div>
</div>
<div class="MylistPart">
<div class="ListItem" style="height:45px;"><span>Box 3</span></div>
<div class="ListItem" style="height:85px;"><span>Box 4</span></div>
<div class="ListItem" style="height:25px;"><span>Box 5</span></div>
</div>
</div>
.MyList
{
overflow:auto;
background:lightgray;
width:240px;
}
.ListItem {
color: #000;
background: white;
border: 1px solid grey;
width:100px;
padding: 0.5em 0.5em 0em 0.5em;
border-radius: 3px;
cursor: pointer;
}
.MylistPart{
float:left;
width:110;
background:lightgreen;
}
EDIT
I edited your solution and added the floating and it is now working fine (jsFiddle
Although special selectors are used for the left and right side columns, these can easily be used with dynamic content where the initial array of boxes has to be split into two parts and then let knockout loop through these two parts to display them.
Why not create a <table>?
<div class="MyList">
<div class="ListItem" style="height:75px;"><span>Box 1</span></div>
<div class="ListItem" style="height:65px;"><span>Box 2</span></div>
<div class="ListItem" style="height:45px;"><span>Box 3</span></div>
<div class="ListItem" style="height:85px;"><span>Box 4</span></div>
<div class="ListItem" style="height:25px;"><span>Box 5</span></div>
</div>
Would change to
<div>
<table>
<tbody>
<tr>
<td>
<div class="ListItem" style="height:75px;"><span>Box 1</span></div>
<div class="ListItem" style="height:45px;"><span>Box 3</span></div>
<div class="ListItem" style="height:25px;"><span>Box 5</span></div>
</td>
<td>
<div class="ListItem" style="height:65px;"><span>Box 2</span></div>
<div class="ListItem" style="height:85px;"><span>Box 4</span></div>
</td>
</tr>
</tbody>
</table>
</div>
*I love tables :P
Here's the JFiddle Re-edit.
Related
Our shopping site has a dropdown menu with main categories and sub-categories. When you hover over a main category, the sub-category menu pops out on the right. The issue is that both menus are contained in the same scrolling container. So you scroll down to find a main category below the current viewport, you hover over a main category and the sub-category pops up on the left, but you have scrolled down, so you only see part of none of the sub-categories. So our current fix, which is not really working is to scroll the container to the top of the sub-categories, which is also the top of the categories. So now your mouse is over a different category and a different set of sub-categories pop out. So basically you cannot view sub-categories for categories below the viewport. Ideally we would make them seperate containers with seperate scrollbars. But that will not look good at all and will not be acceptable.
Note: This only happens when the browser window height is shrunk far enough to cause a vertical scroll bar. Obviously if the window is big enough, no scroll bar is needed and we have no issues.
Here is what it currently looks like. You hover over the 'Electrical' category and the sub-category pops out to the right.
We are using javascript and vue.js, no jquery. I learned this code will scroll the sub-category menu into view, which is not what we want.
var el = document.querySelector('.nav-flyout-menu');
el.scrollIntoView(true);
I think what I want is to actually move, as in set style.top of the sub-category menu to top of the current viewport. I played around with that a little and couldn't anything to work right. Does anyone know how we can successfully solve this issue. Is setting the style.top dynamically the best method? How do I figure out what to set it to? I have tried something like this:
var topBound = document.querySelector('.nav-flyout-menu').getBoundingClientRect().top;
if(topBound < 0) {
let newTop = Math.abs(topBound) + 42;
document.querySelector('.nav-flyout-menu').style.top = newTop + "px";
}
This code worked sometimes and sometimes not.
Update: As requested, here is a fiddle that I have created showcasing my issue. It is not exactly like our site, but I think it is close enough. Make the example height small enough to force a scroll bar and hover over each category. When you scroll down to view the bottom categories, you won't be able to see the top of the subcategories. That is exactly the problem we are currently facing. I think I want to change the top value when it shows the current subcategory. But I can't figure out how to calculate that top value. I used jQuery just to whip out the fiddle example, but we are not using jQuery on our site.
$("a.dropdown-item").hover(
function () {
$(".nav-flyout-menu").removeClass("show");
let category = $.trim($(this).text());
category = category.replace(/\s+/g, '-').toLowerCase();
$("." + category).addClass("show");
},
function () {
}
)
.navbar {
width: 100%;
display: flex;
position: relative;
padding: 0.5rem 1rem;
background-color: #0000cc;
flex-direction: row;
}
.navbar a {
color: #ffffff;
}
.navbar .dropdown-menu a {
color: #000000;
}
ul {
list-style: none;
}
.dropdown-menu {
position: absolute;
top: 100%;
left: 0;
z-index: 1000;
display: block;
float: left;
min-width: 10rem;
padding: .5rem 0;
margin: 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
border: 1px solid rgba(0,0,0,.15);
border-bottom: .5rem solid #cc0000;
padding-right: 1.5rem;
}
.navbar-nav .dropdown-menu {
position: static;
float: none;
}
.navbar-container .dropdown-menu {
max-height: calc(100vh - 150px);
overflow-y: auto;
}
.dropdown-item {
display: block;
width: 100%;
padding: .5rem 1.5rem;
clear: both;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
}
.nav-flyout-root {
position: relative;
display: inline-block;
float: left;
}
.nav-flyout-menu {
display: none;
flex-direction: column;
float: left;
min-width: 10rem;
padding: .5rem 0;
margin: 0;
font-size: 1rem;
color: #212529;
text-align: left;
list-style: none;
background-color: #fff;
background-clip: padding-box;
}
.nav-flyout-menu.show {
display: inline-flex;
}
.flyout-menu-item {
font-weight: 400;
color: #212529;
text-align: inherit;
white-space: nowrap;
background-color: transparent;
border: 0;
display: block;
width: 100%;
padding: .5rem 1.5rem;
clear: both;
}
.submenu div {
display: block;
}
.dropdown-item:focus, .dropdown-item:hover, .dropdown-item a:focus, .dropdown-item a:hover {
color: #fff!important;
text-decoration: none;
background-color: #430984;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="navbar-container">
<div class="navbar">
<ul>
<li>
First
<div class="dropdown-menu">
<div class="d-flex">
<div class="nav-flyout-root">
<a class="dropdown-item">
Computers
</a>
<a class="dropdown-item">
Laptops
</a>
<a class="dropdown-item">
Monitors
</a>
<a class="dropdown-item">
Hard Drives
</a>
<a class="dropdown-item">
Keyboards
</a>
<a class="dropdown-item">
Mice
</a>
<a class="dropdown-item">
Computers
</a>
<a class="dropdown-item">
Laptops
</a>
<a class="dropdown-item">
Monitors
</a>
<a class="dropdown-item">
Hard Drives
</a>
<a class="dropdown-item">
Keyboards
</a>
<a class="dropdown-item">
Mice
</a>
</div>
<div class="nav-flyout-menu position-relative computers">
<div class="flyout-menu-header text-nowrap">
All Computers
</div>
<div class="d-flex flex-grow-1 flex-column submenu">
<div>
Dell
</div>
<div>
HP
</div>
<div>
Asus
</div>
<div>
Compaq
</div>
<div>
Dell
</div>
<div>
Samsung
</div>
<div>
Acer
</div>
</div>
</div>
<div class="nav-flyout-menu position-relative laptops">
<div class="flyout-menu-header text-nowrap">
All Laptops
</div>
<div class="d-flex flex-grow-1 flex-column submenu">
<div>
Acer
</div>
<div>
HP
</div>
<div>
Sony
</div>
<div>
Compaq
</div>
<div>
Vaio
</div>
<div>
Apple
</div>
<div>
Acer
</div>
</div>
</div>
<div class="nav-flyout-menu position-relative monitors">
<div class="flyout-menu-header text-nowrap">
All Monitors
</div>
<div class="d-flex flex-grow-1 flex-column submenu">
<div>
Qnix
</div>
<div>
HP
</div>
<div>
Sony
</div>
<div>
Dell
</div>
<div>
Asus
</div>
<div>
22"
</div>
<div>
23"
</div>
</div>
</div>
<div class="nav-flyout-menu position-relative hard-drives">
<div class="flyout-menu-header text-nowrap">
All Hard Drives
</div>
<div class="d-flex flex-grow-1 flex-column submenu">
<div>
Western Digital
</div>
<div>
Samsung
</div>
<div>
HP
</div>
<div>
Seagate
</div>
<div>
Kingston
</div>
<div>
Crucial
</div>
<div>
SSD
</div>
</div>
</div>
<div class="nav-flyout-menu position-relative keyboards">
<div class="flyout-menu-header text-nowrap">
All Keyboards
</div>
<div class="d-flex flex-grow-1 flex-column submenu">
<div>
Logitech
</div>
<div>
Microsoft
</div>
<div>
Gearhead
</div>
<div>
Razer
</div>
<div>
Cherry MX
</div>
<div>
Mech Blue
</div>
<div>
Mech Red
</div>
</div>
</div>
<div class="nav-flyout-menu position-relative mice">
<div class="flyout-menu-header text-nowrap">
All Mice
</div>
<div class="d-flex flex-grow-1 flex-column submenu">
<div>
Steel Series
</div>
<div>
Microsoft
</div>
<div>
Logitech
</div>
<div>
Razer
</div>
<div>
Cooler Master
</div>
<div>
HyperX
</div>
<div>
Roccat
</div>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
</div>
You can add a class to the active sub-menu element
var el = document.querySelector('.nav-flyout-menu');
el.classList.add("nav-active-sub-menu");
And control it's style with css. Something like:
.nav-active-sub-menu{
position: absolute;
top: 0;
}
Finally got this! I knew this had to be able to be accomplished with some simple javascript. I was right. Element.scrollTop was the key. I don't think this would be possible with CSS alone, someone correct me if I am wrong.
We have an event listener for when a main menu item is hovered to show the submenu. In that listener, I put this code:
let scrollTop = vm.$el.parentElement.parentElement.parentElement.scrollTop;
document.querySelector('.nav-flyout-menu').style.top = scrollTop + "px";
This seems to be working in all my tests.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm trying to filtering my list from bad to excellent like trivago system
if you are going to click this link
you will understand what I'm talking about and I show section on image what I want to do.
When you click button you see styling is removing or adding again and showing hotel list I really didn't understand how to do that ? is there any example
* {
outline: none;
}
button {
cursor: pointer;
background: transparent;
border: none;
padding: 10px;
}
#wrap {
width: 960px;
}
#wrap:before,
#wrap:after {
content: "";
display: table;
clear: both;
}
#filter {
width: 40%;
float: left;
}
#content {
float: right;
width: 59%;
margin-left: 1%;
font-size: 12px;
font-family: sans-serif;
}
.filter-list {
border: 1px solid #ccc;
margin-bottom: 5px;
padding: 10px;
}
<main id="wrap">
<div id="filter">
<button class="bad" data-id="1" style="background:#cc0033;color:#fff" name="rating">bad</button>
<button class="normal" data-id="2" style="background:orange;color:#fff" name="rating">normal</button>
<button class="good" data-id="3" style="background:#99cc00;color:#fff" name="rating">good</button>
<button class="verygood" data-id="4" style="background:green;color:#fff" name="rating">very good</button>
<button class="excellent" data-id="5" style="background:darkgreen;color:#fff" name="rating">excellent</button>
</div>
<!-- filter-->
<div id="content">
<div class="filter-list">
I'm a very good
</div>
<div class="filter-list">
this is the bad list
</div>
<div class="filter-list">
I'm a very good to
</div>
<div class="filter-list">
Excellent!
</div>
<div class="filter-list">
Iııh normal!
</div>
<div class="filter-list">
Good - enough thanks
</div>
<div class="filter-list">
Bad - don't ever..
</div>
<div class="filter-list">
Excellent again
</div>
<div class="filter-list">
isn't bad ? I think yes bad..
</div>
</div>
</main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Look at this code its working like on the trivago page!
$("button").on("click", function (){
$(this).css("opacity", "1");
$(this).nextAll().css("opacity", "1");
$(this).prevAll().css("opacity", "0.5");
});
* {
outline: none;
}
button {
cursor: pointer;
background: transparent;
border: none;
padding: 10px;
}
#wrap {
width: 960px;
}
#wrap:before,
#wrap:after {
content: "";
display: table;
clear: both;
}
#filter {
width: 40%;
float: left;
}
#content {
float: right;
width: 59%;
margin-left: 1%;
font-size: 12px;
font-family: sans-serif;
}
.filter-list {
border: 1px solid #ccc;
margin-bottom: 5px;
padding: 10px;
}
<main id="wrap">
<div id="filter">
<button class="bad" data-id="1" style="background:#cc0033;color:#fff" name="rating">bad</button>
<button class="normal" data-id="2" style="background:orange;color:#fff" name="rating">normal</button>
<button class="good" data-id="3" style="background:#99cc00;color:#fff" name="rating">good</button>
<button class="verygood" data-id="4" style="background:green;color:#fff" name="rating">very good</button>
<button class="excellent" data-id="5" style="background:darkgreen;color:#fff" name="rating">excellent</button>
</div>
<!-- filter-->
<div id="content">
<div class="filter-list">
I'm a very good
</div>
<div class="filter-list">
this is the bad list
</div>
<div class="filter-list">
I'm a very good to
</div>
<div class="filter-list">
Excellent!
</div>
<div class="filter-list">
Iııh normal!
</div>
<div class="filter-list">
Good - enough thanks
</div>
<div class="filter-list">
Bad - don't ever..
</div>
<div class="filter-list">
Excellent again
</div>
<div class="filter-list">
isn't bad ? I think yes bad..
</div>
</div>
</main>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
jQuery is needed btw! You already included it in your snippet.
<div class="main">
<div class="test" style="width:40px;height:100px"><div>
<div class="test" style="width:20px;height:150px;"><div>
<div class="test" style="width:40px;height:100px;"><div>
<div class="test" style="width:40px;height:100px;"><div>
</div>
.main{
position:relative;
border:1px solid red;
width:140px;
height:400px;
}
.test{
float:left;
border:1px solid silver;
position:relative;
padding:10px;
display:inline-block;
}
Div and its height and width are coming dynamically. I am trying to fit the div width in the layout .2 per on raw.
Please suggest.
The height of the container div should be auto. So, it'll take the optimal space to fit the inner elements.
.main {
...
height: auto;
}
Demo
.main {
border: 1px solid red;
width: 140px;
height: auto;
overflow: hidden;
}
.test {
float: left;
border: 1px solid silver;
position: relative;
padding: 10px;
display: inline-block;
}
<div class="main">
<div class="test" style="width:40px;height:100px"></div>
<div class="test" style="width:20px;height:150px;"></div>
<div class="test" style="width:40px;height:100px;"></div>
<div class="test" style="width:40px;height:100px;"></div>
</div>
If you already use Bootstrap you can use its classes to make 2 items per row
https://jsfiddle.net/3mdrrjf8/1/
<div class="main row">
<div class="test col-md-8 col-xs-6" style="height:100px"></div>
<div class="test col-md-8 col-xs-6" style="height:150px;"></div>
<div class="test col-md-8 col-xs-6" style="height:100px;"></div>
<div class="test col-md-8 col-xs-6" style="height:100px;"></div>
</div>
When I click on one of the smaller divs on the left (inside of the div with the class "smallitems", I want for the div on the right (with the class "items") to auto-scroll to the appropriate larger div.
HTML:
<div class="smallitems">
<div class="col">1</div>
<div class="col"> 2 </div>
<div class="col"> 3</div>
<div class="col">4</div>
<div class="col"> 5 </div>
<div class="col">6 </div>
<div class="col"> 7</div>
<div class="col">8</div>
</div>
<div class="items">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">5</div>
</div>
JavaScript (with JQuery):
$('.smallitems .col').on("click", function(){
//how use scroll items show
});
Example:
This is before I click on a div in the left div ("smallitems").
I've now clicked on the number 5 (<div class="col">5</div>) in the left div. As you can see the right div has scrolled to the 5th div (<div class="item">5</div>).
Similar to the above, I've clicked on the number 4, and subsequently have had the right div auto-scroll to the 4th div.
see jfiddle http://jsfiddle.net/h7bLK/
This can be done with anchors. If you replace your div.cols with anchor tags and add an ID to your div.items like this:
<div class="smallitems">
<a class="col" href="#item1">1</a>
<a class="col" href="#item2">2</a>
. . .
</div>
<div class="items">
<div class="item" id="item1">1</div>
<div class="item" id="item2">2</div>
. . .
</div>
Fiddle link
BONUS: You'll be able to link externally to the correct item.
CONS: If the content is smaller than the frame it is rendered in, the whole frame will scroll.
According to requirement, no-need to use javascript or jquery. Its done only using css.
<div class="main-container">
<div class="smallitems">
<div class="col">1</div>
<div class="col"> 2 </div>
<div class="col last-child">3</div>
<div class="col">4</div>
<div class="col">5 </div>
<div class="col last-child">6 </div>
<div class="col"> 7</div>
<div class="col">8</div>
</div>
<div class="items">
<div class="scroll">
<div class="item" id="one">1</div>
<div class="item" id="two">2</div>
<div class="item" id="three">3</div>
<div class="item" id="four">4</div>
<div class="item" id="five">5</div>
<div class="item" id="six">6</div>
<div class="item" id="seven">7</div>
<div class="item" id="eight">8</div>
</div>
</div>
</div>
**Css** :
.main-container{
margin: 20px auto;
width:960px;
overflow: hidden;
border: 1px solid #bababa;
padding: 5px;
}
.smallitems{
overflow: hidden;
float: left;
width:330px;
border: 1px solid #bababa;
display: table;
padding: 10px;
}
.col a{
display: block;
padding: 41px 0;
text-decoration: none;
}
.col{
float:left;
display: table-cell;
vertical-align: middle;
text-align: center;
font-size: 14px;
font-weight: 700;
cursor: pointer;
border: 1px solid #bababa;
height: 100px;
width: 100px;
margin: 0 10px 10px 0;
}
.items{
float: right;
width:580px;
border: 1px solid #bababa;
overflow-y: hidden;
white-space: nowrap;
padding: 10px;
}
.col:nth-child(3),.last-child{
margin-right: 0;
}
.item{
display: inline-block;
text-align: center;
position:relative;
font-size: 14px;
font-weight: 700;
border: 1px solid #bababa;
height: 440px;
width: 180px;
margin: 0 10px 10px 0;
}
$('.smallitems .col').on("click", function(){
var index = $(this).index();
var items = $('.items');
var item = items.children().eq(index);
items.scrollLeft((item.width() - 50) * index);
});
When you add a new div to the items play around with the value of 50.
<div class="container">
<div class="smallitems">
<div class="col">1</div>
<div class="col"> 2 </div>
<div class="col"> 3</div>
<div class="col">4</div>
<div class="col"> 5 </div>
<div class="col">6 </div>
<div class="col"> 7</div>
<div class="col">8</div>
</div>
<div class="items" id="maindiv"> // set id
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">5</div>
</div>
</div>
$('.smallitems').on("click", function(e){
// get click element text and calculate scrollLeft
var scrollLeft = (parseInt($(e.target).text())-1) * 200;
// use jquery animation function
$('#maindiv').animate({scrollLeft :scrollLeft},1100)
});
I want to make a grid 3x3, but problem is that the height on some of the cells will expand with content.
Apart from those height marked with the red arrows, the rest is fixed px.
I made a 3x3 grid with divs to test:
<div id="container">
<div id="one">1</div> <div id="two">2</div> <div id="three">3</div>
<div id="four">4</div> <div id="five">5</div> <div id="six">6</div>
<div id="seven">7</div> <div id="eight">8</div> <div id="nine">9</div>
</div>
#container {
width: 300px;
margin: 0px auto;
}
#one, #two, #three, #four, #five, #six, #seven, #eight, #nine {
width: 100px;
float: left;
padding: 0px; 0px;
text-align: center;
}
But as soon as I change one height they jump out of place.
Any idea?
It looks to me like you want columns.
A structure like this:
<div class="column-thing">
<div class="left-thing">
<div>A</div>
<div>C</div>
</div>
<div class="right-thing">
<div>B<br>B</div>
<div>D</div>
</div>
</div>
And some absolute positioning:
.column-thing {
position: relative;
}
.left-thing {
left: 0;
position: absolute;
right: 50%;
}
.right-thing {
left: 50%;
position: absolute;
right: 0;
}
Voilà.
You can also use lists (ul/ol, li) (without javascript)
<ul class="list">
<li>
<ul>
<li><div>1<br/>1</div></li>
<li><div>2</div></li>
<li><div>3</div></li>
</ul>
</li>
...
</ul>
http://jsfiddle.net/xKjNG/
If you want to ensure that there's three divs in each row, you need to ensure that there's actually a div enclosing each set of three divs...
Try this:
<style>
#one, #two, #three, #four, #five, #six, #seven, #eight, #nine {
width: 100px;
float: left;
padding: 0px; 0px;
text-align: center;
outline: 1px solid black;
}
.clear_float {
clear: both;
}
</style>
<div id="container">
<div id="one">1</div> <div id="two">2</div> <div id="three">3</div><div class = "clear_float"></div>
<div id="four">4</div> <div id="five">5</div> <div id="six">6</div><div class = "clear_float"></div>
<div id="seven">7</div> <div id="eight">8</div> <div id="nine">9</div><div class = "clear_float"></div>
</div>
I'm taking it that the content shouldn't be table based which is why you don't want to use a table.
But an idea would be to use a faux table:
<div class="table">
<div class="tr">
<div class="td">
</div>
<div class="td">
</div>
</div>
</div>
Then on .table add CSS display:table and on .td add CSS display:table-cell.
The naming convention helps work with the code because you'll be used to working with a table's tags structure.
I made a quick example (needed more work than I thought it would): http://jsfiddle.net/cyv6y/1/
needs tidying up a bit but the concept works.