问题
Saying I have an input type="file"
field. One can drop a file on this input
(like in Firefox) instead of clicking "browse" and selecting the file.
Now, I want to customize it a bit, by changing the field's background color when one is about to drop a file in the input
. I cannot really use :hover
since it matches even when you're not drag&dropping. Is there a CSS (pseudo-class) to do that?
And is there a CSS way to style different if the file being dropped is not accepted and if it is? Say, if the field accepts only PNG files using accept
attributes, I would make the field green if you're about to drop a PNG file on it, and red if that's another type of file.
Is there a CSS way to do these today? Is there a planned way to do so in CSS (like in upcoming specs/in current specs but not implements anywhere)?
回答1:
UPDATE: Thanks to @Renato's comment, according to https://github.com/w3c/csswg-drafts/issues/2257, the drop pseudo-class has been dropped now.
There is :drop
and :drop()
pseudo-class, which is currently in Working Draft status.
According to http://css4.rocks/selectors-level-4/drag-and-drop-pseudo-class.php, the browser support is not good.
For "file being dropped is not accepted" case, :drop(invalid active)
is expected to work, in future.
回答2:
I had the same question and solved it a little differently than nashcheez. Still using JavaScript, though (I used jQuery here to simplify things):
function drag(ev) {
ev.dataTransfer.setData("text", "foo");
}
function allowDrop(ev) {
$(ev.target).attr("drop-active", true);
ev.preventDefault();
}
function leaveDropZone(ev) {
$(ev.target).removeAttr("drop-active");
}
function drop(ev) {
ev.preventDefault();
$(ev.target).removeAttr("drop-active");
alert(ev.dataTransfer.getData("text"));
}
#draggableItem {
height: 50px;
width: 150px;
background-color: #eee;
}
#dropZone {
height: 50px;
width: 150px;
background-color: #efe;
}
#dropZone[drop-active=true] {
box-shadow: inset 0px 0px 0px 2px #00C;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="draggableItem" draggable="true" ondragstart="drag(event);">Drag Me</div>
<div id="dropZone" ondragover="allowDrop(event);" ondragleave="leaveDropZone(event);" ondrop="drop(event);">Drop Here</div>
I've tested this on Safari, Firefox and Chrome, but I haven't tried IE. I'm probably breaking a rule with the custom attribute, but it seems to work while I'm waiting for CSS4.
回答3:
There is absolutely no pure css cross-browser solution currently for changing element's properties when dragging and dropping elements into the browser window.
What you are trying to do here can be achieved by Javascript/jQuery using a hidden container and showing it only when the object is inside the draggable container.
There is this demo I had saved earlier if you would like to have a look into:
var resetTimer;
var reset = function() {
$('#d1').hide();
};
var f = function(e) {
var srcElement = e.srcElement ? e.srcElement : e.target;
if ($.inArray('Files', e.dataTransfer.types) > -1) {
e.stopPropagation();
e.preventDefault();
e.dataTransfer.dropEffect = (srcElement.id == 'd1') ? 'copy' : 'none';
if (e.type == "dragover") {
if (resetTimer) {
clearTimeout(resetTimer);
}
$('#d1').show();
console.info('dropped on <' + srcElement.tagName.toLowerCase() + ' id="' + srcElement.id + '">\n\ne.dataTransfer.types is ' + e.dataTransfer.types + '\n\ne.dataTransfer.files.length is ' + (e.dataTransfer.files ? e.dataTransfer.files.length : 0));
} else if (e.type == "dragleave") {
resetTimer = window.setTimeout(reset, 25);
} else if (e.type == "drop") {
reset();
alert('dropped on <' + srcElement.tagName.toLowerCase() + ' id="' + srcElement.id + '">\n\ne.dataTransfer.files.length is ' + (e.dataTransfer.files ? e.dataTransfer.files.length : 0));
}
}
};
document.body.addEventListener("dragleave", f, false);
document.body.addEventListener("dragover", f, false);
document.body.addEventListener("drop", f, false);
body {
border: 1px solid black;
}
#d0,
#d2 {
border: 1px solid black;
}
#d1 {
border: 1px solid black;
display: none;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div id="d0">drag files onto this page</div>
<div id="d1">-> drop here <-</div>
<div id="d2">and stuff will happen</div>
</body>
来源:https://stackoverflow.com/questions/42853699/is-there-a-css-drop-hover-pseudo-class