Index: src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java
===================================================================
--- src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java	(revision 15080)
+++ src/org/openstreetmap/josm/data/validation/tests/MapCSSTagChecker.java	(working copy)
@@ -866,7 +866,10 @@
             env.clearSelectorMatchingInformation();
             if (partialSelection && r.selector instanceof Selector.ChildOrParentSelector) {
                 ChildOrParentSelector sel = (Selector.ChildOrParentSelector) r.selector;
-                if (sel.type == ChildOrParentSelectorType.ELEMENT_OF && p.getDataSet() != null) {
+                boolean needEnclosing = sel.type == ChildOrParentSelectorType.ELEMENT_OF
+                        || sel.type == ChildOrParentSelectorType.SUBSET_OR_EQUAL
+                        || sel.type == ChildOrParentSelectorType.NOT_SUBSET_OR_EQUAL;
+                if (needEnclosing && p.getDataSet() != null) {
                     List<OsmPrimitive> toCheck = new ArrayList<>();
                     toCheck.addAll(p.getDataSet().searchWays(p.getBBox()));
                     toCheck.addAll(p.getDataSet().searchRelations(p.getBBox()));
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(revision 15080)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/MapCSSParser.jj	(working copy)
@@ -217,6 +217,10 @@
 |   < FULLSTOP: "." >
 |   < DEG: "°" >
 |   < ELEMENT_OF: "∈" >
+|   < SUBSET_OR_EQUAL: "⊆" >
+|   < NOT_SUBSET_OR_EQUAL: "⊈" >
+|   < SUPERSET_OR_EQUAL: "⊇" >
+|   < NOT_SUPERSET_OR_EQUAL: "⊉" >
 |   < CROSSING: "⧉" >
 |   < PERCENT: "%" >
 |   < COMMENT_START: "/*" > : COMMENT
@@ -692,6 +696,14 @@
             |
                 <ELEMENT_OF> { type = Selector.ChildOrParentSelectorType.ELEMENT_OF; }
             |
+                <SUBSET_OR_EQUAL> { type = Selector.ChildOrParentSelectorType.SUBSET_OR_EQUAL; }
+            |
+                <NOT_SUBSET_OR_EQUAL> { type = Selector.ChildOrParentSelectorType.NOT_SUBSET_OR_EQUAL; }
+            |
+                <SUPERSET_OR_EQUAL> { type = Selector.ChildOrParentSelectorType.SUPERSET_OR_EQUAL; }
+            |
+                <NOT_SUPERSET_OR_EQUAL> { type = Selector.ChildOrParentSelectorType.NOT_SUPERSET_OR_EQUAL; }
+            |
                 <CROSSING> { type = Selector.ChildOrParentSelectorType.CROSSING; }
             )
             w()
Index: src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java
===================================================================
--- src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(revision 15080)
+++ src/org/openstreetmap/josm/gui/mappaint/mapcss/Selector.java	(working copy)
@@ -117,7 +117,7 @@
      * @see ChildOrParentSelector
      */
     enum ChildOrParentSelectorType {
-        CHILD, PARENT, ELEMENT_OF, CROSSING, SIBLING
+        CHILD, PARENT, ELEMENT_OF, SUBSET_OR_EQUAL, NOT_SUBSET_OR_EQUAL, SUPERSET_OR_EQUAL, NOT_SUPERSET_OR_EQUAL, CROSSING, SIBLING,
     }
 
     /**
@@ -312,12 +312,15 @@
             }
         }
 
+        /**
+         * Finds elements which are inside the right element, collects those in {@code children}
+         * If e.osm is a node it finds nodes with with equal position.
+         */
         private class ContainsFinder extends AbstractFinder {
             protected List<IPrimitive> toCheck;
 
             protected ContainsFinder(Environment e) {
                 super(e);
-                CheckParameterUtil.ensureThat(!(e.osm instanceof INode), "Nodes not supported");
             }
 
             @Override
@@ -336,7 +339,12 @@
                 if (toCheck == null || toCheck.isEmpty())
                     return;
 
-                if (e.osm instanceof IWay) {
+                if (e.osm instanceof INode) {
+                    for (IPrimitive p : toCheck) {
+                        if (p instanceof INode && ((INode) p).getCoor().equals(((INode) e.osm).getCoor()))
+                            addToChildren(e, p);
+                    }
+                } else if (e.osm instanceof IWay) {
                     for (IPrimitive p : Geometry.filterInsidePolygon(toCheck, (IWay<?>) e.osm)) {
                         addToChildren(e, p);
                     }
@@ -348,6 +356,72 @@
             }
         }
 
+        /**
+         * Finds elements which are inside the left element, or in other words, it finds elements enclosing e.osm.
+         * The found enclosing elements are collected in {@code e.children}.
+         */
+        private class InsideOrEqualFinder extends AbstractFinder {
+
+            protected InsideOrEqualFinder(Environment e) {
+                super(e);
+            }
+
+            @Override
+            public void visit(INode n) {
+                // rather special case: nodes with equal coordinates
+                if (e.osm instanceof INode && n.getCoor().equals(((INode) e.osm).getCoor())
+                        && left.matches(new Environment(n).withParent(e.osm))) {
+                    addToChildren(e, n);
+                }
+            }
+
+            @Override
+            public void visit(IWay<?> w) {
+                if (left.matches(new Environment(w).withParent(e.osm))
+                        && w.getBBox().bounds(e.osm.getBBox())
+                        && !Geometry.filterInsidePolygon(Collections.singletonList(e.osm), w).isEmpty()) {
+                    addToChildren(e, w);
+                }
+            }
+
+            @Override
+            public void visit(IRelation<?> r) {
+                if (r instanceof Relation && r.isMultipolygon() && r.getBBox().bounds(e.osm.getBBox())
+                        && left.matches(new Environment(r).withParent(e.osm))
+                        && !Geometry.filterInsideMultipolygon(Collections.singletonList(e.osm), (Relation) r).isEmpty()) {
+                    addToChildren(e, r);
+                }
+            }
+        }
+
+        private void visitBBox(Environment e, AbstractFinder finder) {
+            boolean nodesOnly = finder instanceof ContainsFinder && e.osm instanceof INode;
+            if (left instanceof OptimizedGeneralSelector) {
+                if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.NODE)) {
+                    finder.visit(e.osm.getDataSet().searchNodes(e.osm.getBBox()));
+                }
+                if (!nodesOnly) {
+                    if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.WAY)) {
+                        finder.visit(e.osm.getDataSet().searchWays(e.osm.getBBox()));
+                    }
+                    if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.RELATION)) {
+                        finder.visit(e.osm.getDataSet().searchRelations(e.osm.getBBox()));
+                    }
+                }
+            } else {
+                finder.visit(e.osm.getDataSet().searchNodes(e.osm.getBBox()));
+                if (!nodesOnly) {
+                    finder.visit(e.osm.getDataSet().searchWays(e.osm.getBBox()));
+                    finder.visit(e.osm.getDataSet().searchRelations(e.osm.getBBox()));
+                }
+            }
+        }
+
+        private static boolean isArea(IPrimitive p) {
+            return (p instanceof IWay && ((IWay<?>) p).isClosed() && ((IWay<?>) p).getNodesCount() >= 4)
+                    || (p instanceof IRelation && p.isMultipolygon() && !p.isIncomplete());
+        }
+
         @Override
         public boolean matches(Environment e) {
 
@@ -354,33 +428,38 @@
             if (!right.matches(e))
                 return false;
 
-            if (ChildOrParentSelectorType.ELEMENT_OF == type) {
+            if (ChildOrParentSelectorType.ELEMENT_OF == type || ChildOrParentSelectorType.SUBSET_OR_EQUAL == type
+                    || ChildOrParentSelectorType.NOT_SUBSET_OR_EQUAL == type) {
 
-                if (e.osm instanceof INode || e.osm.getDataSet() == null) {
-                    // nodes cannot contain elements
+                if (e.osm.getDataSet() == null || (ChildOrParentSelectorType.ELEMENT_OF == type && e.osm instanceof INode)) {
+                    // for ELEMENT_OF nodes cannot contain elements
                     return false;
                 }
-
+                if (!(e.osm instanceof INode) && !isArea(e.osm)) {
+                    return false;
+                }
                 ContainsFinder containsFinder = new ContainsFinder(e);
                 e.parent = e.osm;
 
-                if (left instanceof OptimizedGeneralSelector) {
-                    if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.NODE)) {
-                        containsFinder.visit(e.osm.getDataSet().searchNodes(e.osm.getBBox()));
-                    }
-                    if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.WAY)) {
-                        containsFinder.visit(e.osm.getDataSet().searchWays(e.osm.getBBox()));
-                    }
-                    if (((OptimizedGeneralSelector) left).matchesBase(OsmPrimitiveType.RELATION)) {
-                        containsFinder.visit(e.osm.getDataSet().searchRelations(e.osm.getBBox()));
-                    }
-                } else {
-                    // use slow test
-                    containsFinder.visit(e.osm.getDataSet().allPrimitives());
+                visitBBox(e, containsFinder);
+                containsFinder.execGeometryTests();
+                if (ChildOrParentSelectorType.ELEMENT_OF == type || ChildOrParentSelectorType.SUBSET_OR_EQUAL == type)
+                    return e.children != null;
+                return e.children == null;
+            } else if (ChildOrParentSelectorType.SUPERSET_OR_EQUAL == type || ChildOrParentSelectorType.NOT_SUPERSET_OR_EQUAL == type) {
+                if (e.osm.getDataSet() == null || (e.osm instanceof INode && ((INode) e.osm).getCoor() == null)) {
+                    return false;
                 }
-                containsFinder.execGeometryTests();
-                return e.children != null;
+                if (!(e.osm instanceof INode) && !isArea(e.osm)) {
+                    return false;
+                }
 
+                InsideOrEqualFinder insideOrEqualFinder = new InsideOrEqualFinder(e);
+                e.parent = e.osm;
+
+                visitBBox(e, insideOrEqualFinder);
+                return ChildOrParentSelectorType.SUPERSET_OR_EQUAL == type ? e.children != null : e.children == null;
+
             } else if (ChildOrParentSelectorType.CROSSING == type && e.osm instanceof IWay) {
                 e.parent = e.osm;
                 if (right instanceof OptimizedGeneralSelector
